{
  "id": "9Z7ucLPwzGsulHly",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Product Backlog RAG Assistant",
  "tags": [
    {
      "id": "RKP1E9UWmf8t5UuL",
      "name": "Draft",
      "createdAt": "2026-07-01T15:26:33.507Z",
      "updatedAt": "2026-07-01T15:26:33.507Z"
    }
  ],
  "nodes": [
    {
      "id": "cb59bb61-dda4-4f5e-817e-98360c670425",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        1360
      ],
      "parameters": {
        "width": 480,
        "height": 800,
        "content": "## Product Backlog RAG Assistant\n\n### How it works\n\n1. A form submission triggers extraction of file content and stores it in a Supabase vector store.\n2. Default data and embeddings are prepared to initialize the knowledge base.\n3. A Slack slash command triggers an immediate acknowledgment and initiates a RAG agent to answer queries.\n4. The RAG agent uses embeddings to search the vector store and generate a response via an AI model.\n5. The answer is posted back to Slack via an HTTP request.\n\n### Setup steps\n\n- - [ ] Configure the form trigger (e.g., n8n form or webhook) to capture file uploads.\n- - [ ] Set up Supabase credentials for the vector store node.\n- - [ ] Configure Google Gemini API key for both embeddings nodes.\n- - [ ] Set up Slack credentials for the slash command webhook and outgoing message.\n- - [ ] Optionally configure the AI model (OpenRouter) used in the RAG agent.\n\n### Customization\n\nYou can modify the form fields to capture different metadata, switch to another vector store like Pinecone, adjust the prompt in the RAG agent for answer style, or change the Slack response format."
      },
      "typeVersion": 1
    },
    {
      "id": "198c996f-69e1-4e77-9957-3d967351adc1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 272,
        "content": "## Form-based Data Ingestion\n\nExtracts file content from form submissions and stores it in a Supabase vector store."
      },
      "typeVersion": 1
    },
    {
      "id": "4fb98b89-25d1-4f11-a44c-52e17c812dae",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        1664
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 304,
        "content": "## Default Knowledge Base Setup\n\nLoads default data and generates embeddings to initialize the vector store."
      },
      "typeVersion": 1
    },
    {
      "id": "42d74ffd-0857-4557-b338-e16adb09915d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 464,
        "content": "## Slack Command Acknowledgment\n\nReceives Slack slash commands and sends an immediate acknowledgment response."
      },
      "typeVersion": 1
    },
    {
      "id": "34097603-df2e-4a23-89f7-9a197262d6cd",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        2000
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 720,
        "content": "## RAG Agent Processing\n\nGenerates query embeddings and runs the AI agent to search the knowledge base."
      },
      "typeVersion": 1
    },
    {
      "id": "88156866-a547-4be2-9ec5-5abf941f04b2",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        1936
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 368,
        "content": "## Answer Posting to Slack\n\nPosts the generated answer back to Slack via an HTTP request."
      },
      "typeVersion": 1
    },
    {
      "id": "8f7589c1-e586-43dd-94e5-05660ad604d8",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -496,
        1472
      ],
      "parameters": {
        "options": {},
        "formTitle": "Index Product Backlog",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Backlog PDF",
              "acceptFileTypes": ".pdf"
            }
          ]
        },
        "formDescription": "Upload your product backlog PDF to make it searchable via Slack."
      },
      "typeVersion": 2.5
    },
    {
      "id": "7b092acb-ffe1-44d2-855a-e995fd5ecaa2",
      "name": "Extract from File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -176,
        1472
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "Backlog_PDF"
      },
      "typeVersion": 1.1
    },
    {
      "id": "01072a7d-6450-4b7d-a006-e286ce421f52",
      "name": "Supabase Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "position": [
        160,
        1472
      ],
      "parameters": {
        "mode": "insert",
        "options": {},
        "tableName": {
          "__rl": true,
          "mode": "list",
          "value": "backlog_documents",
          "cachedResultName": "backlog_documents"
        },
        "embeddingBatchSize": "=200"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "48d3b927-65c1-49ba-ba88-774987721a2e",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        320,
        1792
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "2f6e1e57-769c-4aac-9824-c8853b23da8c",
      "name": "Embeddings Google Gemini",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        112,
        1792
      ],
      "parameters": {
        "modelName": "models/gemini-embedding-001"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6725f522-3fab-4d1f-9000-02ff18b01bb0",
      "name": "Slack Slash Command Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -512,
        1984
      ],
      "parameters": {
        "path": "backlog-query",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "0646ffd6-ec93-4a8c-896d-11a3c9bbdcbf",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -288,
        1840
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"response_type\": \"in_channel\",\n  \"text\": \"\ud83d\udd0d *Question backlog :* {{ $('Slack Slash Command Trigger').item.json.body.text }}\\n_Recherche en cours..._\"\n}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "99083ddb-836f-4cdd-be74-4f6a42bef71c",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        -16,
        2384
      ],
      "parameters": {
        "model": "openrouter/free",
        "options": {
          "temperature": 0.8
        }
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "68d3925f-3768-4d33-b59d-9448738873ae",
      "name": "search_backlog",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "position": [
        304,
        2368
      ],
      "parameters": {
        "mode": "retrieve-as-tool",
        "topK": 5,
        "options": {},
        "tableName": {
          "__rl": true,
          "mode": "list",
          "value": "backlog_documents",
          "cachedResultName": "backlog_documents"
        },
        "toolDescription": "Search the product backlog for user stories, epics, acceptance criteria, and requirements. Use this to answer any question about the backlog content."
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "96917c05-b096-40bb-baff-0c7d95c109db",
      "name": "Embeddings Google Gemini1",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        304,
        2544
      ],
      "parameters": {
        "modelName": "models/gemini-embedding-001"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c59dc945-1123-4b38-ba2c-78d255f27236",
      "name": "RAG Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        160,
        2128
      ],
      "parameters": {
        "text": "={{ $('Slack Slash Command Trigger').item.json.body.text }}",
        "options": {
          "systemMessage": "You are a product backlog assistant. You answer questions about a product backlog by searching it with the \"search_backlog\" tool.\n\nRules:\n- ALWAYS use the search_backlog tool before answering. Never answer from memory.\n- Base your answer ONLY on the retrieved backlog content. Do not invent stories, \n  IDs, or requirements that aren't in the search results.\n- If the backlog doesn't contain the answer, say so clearly: \"Je ne trouve pas \n  cette information dans le backlog.\"\n- When you cite a user story, include its ID (e.g. NTS-1) so the user can find it.\n- Answer in the same language as the question.\n- Be concise and structured. Use bullet points for lists of stories.\n- For \"how many\" or \"list all\" questions, search broadly and enumerate what you find.\n\nFormat your answer for Slack: use *bold* (single asterisks), bullet points \nwith \u2022, and keep it scannable."
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "351a927c-20ab-44c2-906d-f4e796fc9c76",
      "name": "Post Answer to Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        2128
      ],
      "parameters": {
        "url": "={{ $('Slack Slash Command Trigger').item.json.body.response_url }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({\n  response_type: \"in_channel\",\n  replace_original: true,\n  blocks: [\n    {\n      type: \"section\",\n      text: {\n        type: \"mrkdwn\",\n        text: `\ud83d\udd0d *Question :* ${$('Slack Slash Command Trigger').item.json.body.text}`\n      }\n    },\n    { type: \"divider\" },\n    {\n      type: \"section\",\n      text: {\n        type: \"mrkdwn\",\n        text: ($json.output && $json.output.trim().length > 0)\n          ? $json.output\n          : \"_Je n'ai pas pu g\u00e9n\u00e9rer de r\u00e9ponse. V\u00e9rifie que le backlog est bien index\u00e9._\"\n      }\n    }\n  ]\n}) }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "eb73d118-6af1-4a21-9550-668968d7ae60",
  "connections": {
    "RAG Agent": {
      "main": [
        [
          {
            "node": "Post Answer to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "search_backlog": {
      "ai_tool": [
        [
          {
            "node": "RAG Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "RAG Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini": {
      "ai_embedding": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini1": {
      "ai_embedding": [
        [
          {
            "node": "search_backlog",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Slack Slash Command Trigger": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          },
          {
            "node": "RAG Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}