{ "name": "LLM Wiki — pre-compiled RAG with Google Docs & Sheets", "nodes": [ { "parameters": { "formTitle": "Upload Document", "formDescription": "Upload your knowledge document", "formFields": { "values": [ { "fieldLabel": "Document", "fieldType": "file", "fieldName": "doc", "acceptFileTypes": ".md, .txt" } ] }, "options": {} }, "type": "n8n-nodes-base.formTrigger", "typeVersion": 2.5, "position": [ 0, 112 ], "id": "57e78e69-c698-4fbe-963a-1e43d3e1dc81", "name": "On form submission", "webhookId": "" }, { "parameters": { "promptType": "define", "text": "=Here is the content of the document the user uploaded. Organize it and write it into the Wiki:\n{{ $json.doc }}", "options": { "systemMessage": "You are a Wiki knowledge-writing assistant.\nYour only job is to organize the received document content and write it completely into the Wiki knowledge base.\n\n## Tools\n\n- get_indexs: Read the index sheet. Returns every entry's topic, doc_id, keywords, summary.\n- create_wiki_page: Create a new Wiki Doc. Input a topic name, returns a doc_id.\n- write_wiki: Append new content to the end of a Wiki Doc. Input doc_id + content.\n- write_index: Add a new row to the index sheet (for brand-new entries). Input topic, doc_id, keywords, summary.\n- update_wiki: Update an existing index entry's keywords and summary. Input topic + new values.\n\n## Workflow\n\n### Step 1: Read the index (mandatory)\nCall get_indexs to get all existing entries.\nYou MUST complete this before doing anything else.\n\n### Step 2: Analyze the document\nBreak the document content into one or more topics.\nHandle each topic independently.\n\n### Step 3: For each topic, decide\n\n**If the topic already exists in the index:**\n1. Call write_wiki (with the existing doc_id) to Append the new knowledge to the end of the Doc.\n2. Call update_wiki to refresh that entry's keywords and summary.\n-> update_wiki is the final step of this branch. Not calling it means the topic is not finished.\n\n**If the topic does NOT exist in the index:**\n1. Call create_wiki_page (input topic) to get a new doc_id.\n2. Call write_wiki (with the new doc_id) to write the initial content.\n3. Call write_index to add the new entry to the index sheet.\n-> write_index is the final step of this branch. Not calling it means the topic is not finished.\n\n### Step 4: Confirm completion (mandatory)\nBefore reporting any result to the user, verify every topic has finished its final step:\n- Existing topic: update_wiki has been called ✓\n- New topic: write_index has been called ✓\nIf any topic has not finished its final step, complete it first before reporting.\n\n### Step 5: Report\nFormat:\n\n✅ Updated topics: [topic name] (doc_id: xxx)\n🆕 New pages created: [topic name] (doc_id: xxx)\n\n## Writing format\n\n- Structure: bullet the core concepts, one point per line.\n- Always append at the end: Source: uploaded document | Date: {{$now}}\n- Mode: Append. Never delete or overwrite existing content.\n\n## Hard rules\n\n- Until get_indexs has been called, do not run any other tool.\n- Until the index has been updated, do not report the task as complete.\n- write_wiki is never the final step.\nYou MUST perform every operation via a tool call (function call).\nNEVER describe an action in text such as \"I will call XXX\" or \"Calling XXX with input\".\nDescribing an action is not performing it. Only an actual tool call counts as completing the task." } }, "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 3.1, "position": [ 704, 0 ], "id": "1a52474b-dc56-409f-b9f5-76655dd842f5", "name": "AI Agent" }, { "parameters": { "operation": "text", "binaryPropertyName": "doc", "destinationKey": "doc", "options": {} }, "type": "n8n-nodes-base.extractFromFile", "typeVersion": 1.1, "position": [ 224, 112 ], "id": "b35641d7-1830-4951-9007-f1d5870fc223", "name": "Extract from File" }, { "parameters": { "descriptionType": "manual", "toolDescription": "讀取 Wiki index sheet,取得所有現有條目。\n\n回傳每筆條目的:topic、doc_id、keywords、summary、last_updated\n\n這是每次流程的第一步,必須先呼叫才能判斷主題是否已存在。", "authentication": "serviceAccount", "documentId": { "__rl": true, "value": "YOUR_INDEX_SHEET_ID", "mode": "list", "cachedResultName": "index", "cachedResultUrl": "" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "工作表1", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_INDEX_SHEET_ID/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheetsTool", "typeVersion": 4.7, "position": [ 576, 224 ], "id": "71b93dc0-d918-42dd-88ca-30a75b807130", "name": "get_indexs" }, { "parameters": { "toolDescription": "=建立一個新的 Google Docs Wiki 頁面。\n\n輸入:\n- doc_title:頁面標題(主題名稱)\n\n回傳:\n- doc_id:新建頁面的 Google Doc ID(後續 write_wiki 和 write_index 都需要這個值)\n\n注意:建立後必須繼續呼叫 write_wiki 寫入內容,再呼叫 write_index 更新索引,任務才算完成。", "method": "POST", "url": "https://YOUR-N8N-HOST/webhook/YOUR-CREATE-WIKI-PAGE-WEBHOOK-ID", "sendBody": true, "bodyParameters": { "parameters": [ { "name": "doc_title", "value": "={{ $fromAI('doc_title') }}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequestTool", "typeVersion": 4.4, "position": [ 704, 224 ], "id": "8e9efcaa-e434-444a-98bc-347fc0c9b989", "name": "create_wiki_page" }, { "parameters": { "modelName": "models/gemini-flash-latest", "options": {} }, "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini", "typeVersion": 1.1, "position": [ 448, 224 ], "id": "7cb78f89-1c14-435d-90aa-1f2dcb3bd07d", "name": "Gemini" }, { "parameters": { "options": {} }, "type": "@n8n/n8n-nodes-langchain.chatTrigger", "typeVersion": 1.4, "position": [ 240, 464 ], "id": "d437ecd9-f215-4e9e-850b-9f041ef9168e", "name": "When chat message received", "webhookId": "" }, { "parameters": { "descriptionType": "manual", "toolDescription": "讀取指定 Wiki Google Doc 的完整內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID(從 get_indexs 取得)\n\n回傳:該頁面的全文內容,用於回答用戶問題。", "operation": "get", "documentURL": "={{ $fromAI('doc_id') }}" }, "type": "n8n-nodes-base.googleDocsTool", "typeVersion": 2, "position": [ 720, 688 ], "id": "bc9be3ed-9db6-4efa-b517-ea06c56b0c8d", "name": "read_wiki" }, { "parameters": { "options": { "systemMessage": "You are a Wiki knowledge-query assistant.\nYour job is to answer the user's question by finding the answer in the Wiki knowledge base.\n\nTools:\n- get_indexs: Read the index sheet. Returns every entry's topic, doc_id, keywords, summary.\n- read_wiki: Read the full content of a given Wiki Doc. Input doc_id, returns the full text.\n\nOrder of execution:\n1. Call get_indexs and browse every entry's keywords and summary.\n2. Decide which doc_id (or doc_ids) is most relevant to the question.\n3. Call read_wiki (with the doc_id) to read the content.\n4. Answer the user based on what you read.\n\nNotes:\n- Read-only. Do not modify any Wiki content.\n- If no relevant topic is found in the index, tell the user plainly: \"The Wiki does not yet contain this topic.\"\n- Base your answer on the Wiki content. Do not make things up." } }, "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 3.1, "position": [ 592, 464 ], "id": "2b77a40c-e0b7-477f-aac1-50d80fe4deec", "name": "AI Agent1" }, { "parameters": { "modelName": "models/gemma-4-31b-it", "options": {} }, "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini", "typeVersion": 1.1, "position": [ 464, 688 ], "id": "e32a353a-adb9-4821-8308-784af0c93129", "name": "Gemini1" }, { "parameters": { "descriptionType": "manual", "toolDescription": "在 index sheet 新增或更新一筆條目。這是每次寫入流程的最後一步,沒有呼叫這個工具代表任務尚未完成。\n\n輸入:\n- topic:主題名稱\n- doc_id:對應的 Google Doc ID(從 create_wiki_page 取得,或從 get_indexs 讀出)\n- keywords:逗號分隔的關鍵詞列表\n- summary:這篇 Wiki 目前涵蓋內容的一句話摘要\n- last_updated:今天日期,格式 YYYY-MM-DD\n\n行為:doc_id 已存在則更新該行,不存在則新增一行。", "authentication": "serviceAccount", "operation": "appendOrUpdate", "documentId": { "__rl": true, "value": "YOUR_INDEX_SHEET_ID", "mode": "list", "cachedResultName": "index", "cachedResultUrl": "" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "工作表1", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_INDEX_SHEET_ID/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "doc_id": "={{ $fromAI('doc_id') }}", "topic": "={{ $fromAI('topic') }}", "keywords": "={{ $fromAI('keywords') }}", "summary": "={{ $fromAI('summary') }}", "last_updated": "={{ $fromAI('last_updated') }}" }, "matchingColumns": [ "doc_id" ], "schema": [ { "id": "topic", "displayName": "topic", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "doc_id", "displayName": "doc_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "keywords", "displayName": "keywords", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "summary", "displayName": "summary", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "last_updated", "displayName": "last_updated", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheetsTool", "typeVersion": 4.7, "position": [ 832, 224 ], "id": "6091001d-c6e3-478d-bdbd-6ab4afededc2", "name": "write_index" }, { "parameters": { "descriptionType": "manual", "toolDescription": "讀取指定 Wiki Google Doc 的完整內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID(從 get_indexs 取得)\n\n回傳:該頁面的全文內容,用於回答用戶問題。", "authentication": "serviceAccount", "documentId": { "__rl": true, "value": "YOUR_INDEX_SHEET_ID", "mode": "list", "cachedResultName": "index", "cachedResultUrl": "" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "工作表1", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_INDEX_SHEET_ID/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheetsTool", "typeVersion": 4.7, "position": [ 848, 688 ], "id": "d9edd457-07a4-46d6-810b-c1c988ac9525", "name": "get_indexs1" }, { "parameters": {}, "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow", "typeVersion": 1.4, "position": [ 592, 688 ], "id": "48c22e61-9260-4c77-b782-cf3cd049e371", "name": "Simple Memory" }, { "parameters": { "descriptionType": "manual", "toolDescription": "取代指定 Wiki Google Doc 中的特定文字段落。用於修改或更正既有頁面中的內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID\n- old_text:要被取代的原始文字\n- new_text:取代後的新文字\n\n注意:呼叫完畢後必須繼續呼叫 write_index 更新索引中的 keywords 和 summary。", "operation": "update", "documentURL": "={{ $fromAI('doc_id') }}", "actionsUi": { "actionFields": [ { "action": "replaceAll", "text": "={{ $fromAI('old_text') }}", "replaceText": "={{ $fromAI('new_text') }}" } ] } }, "type": "n8n-nodes-base.googleDocsTool", "typeVersion": 2, "position": [ 960, 224 ], "id": "811d333c-2d32-4238-a03a-bf35e2d7bd82", "name": "update_wiki" }, { "parameters": { "descriptionType": "manual", "toolDescription": "將新內容 Append(插入)到指定的 Wiki Google Doc 末尾。用於寫入全新頁面的初始內容,或在既有頁面末尾新增知識。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID\n- text:要寫入的內容\n\n注意:這是新增內容,不會刪除原有內容。呼叫完畢後必須繼續呼叫 write_index 更新索引。", "operation": "update", "documentURL": "={{ $fromAI('doc_id') }}", "actionsUi": { "actionFields": [ { "action": "insert", "text": "={{ $fromAI('text') }}" } ] } }, "type": "n8n-nodes-base.googleDocsTool", "typeVersion": 2, "position": [ 1088, 224 ], "id": "64891a23-95d7-4d9f-a8ff-a0e74798737e", "name": "write_wiki" }, { "parameters": { "content": "## 1. Ingest (Write)", "height": 448, "width": 1328, "color": 2 }, "type": "n8n-nodes-base.stickyNote", "position": [ -96, -80 ], "typeVersion": 1, "id": "e6626b8e-1717-40f1-9094-e95d3455eec8", "name": "Sticky Note" }, { "parameters": { "content": "## 2. Query (Read)", "height": 448, "width": 1328, "color": 4 }, "type": "n8n-nodes-base.stickyNote", "position": [ -96, 384 ], "typeVersion": 1, "id": "35370a11-27e8-4b58-97db-725cf7af1319", "name": "Sticky Note1" } ], "pinData": {}, "connections": { "On form submission": { "main": [ [ { "node": "Extract from File", "type": "main", "index": 0 } ] ] }, "Extract from File": { "main": [ [ { "node": "AI Agent", "type": "main", "index": 0 } ] ] }, "get_indexs": { "ai_tool": [ [ { "node": "AI Agent", "type": "ai_tool", "index": 0 } ] ] }, "create_wiki_page": { "ai_tool": [ [ { "node": "AI Agent", "type": "ai_tool", "index": 0 } ] ] }, "Gemini": { "ai_languageModel": [ [ { "node": "AI Agent", "type": "ai_languageModel", "index": 0 } ] ] }, "When chat message received": { "main": [ [ { "node": "AI Agent1", "type": "main", "index": 0 } ] ] }, "read_wiki": { "ai_tool": [ [ { "node": "AI Agent1", "type": "ai_tool", "index": 0 } ] ] }, "Gemini1": { "ai_languageModel": [ [ { "node": "AI Agent1", "type": "ai_languageModel", "index": 0 } ] ] }, "write_index": { "ai_tool": [ [ { "node": "AI Agent", "type": "ai_tool", "index": 0 } ] ] }, "get_indexs1": { "ai_tool": [ [ { "node": "AI Agent1", "type": "ai_tool", "index": 0 } ] ] }, "Simple Memory": { "ai_memory": [ [ { "node": "AI Agent1", "type": "ai_memory", "index": 0 } ] ] }, "update_wiki": { "ai_tool": [ [ { "node": "AI Agent", "type": "ai_tool", "index": 0 } ] ] }, "write_wiki": { "ai_tool": [ [ { "node": "AI Agent", "type": "ai_tool", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1", "binaryMode": "separate" }, "tags": [] }