{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "3b741f12-c482-4cad-add1-d982b4bae2d9",
      "name": "\ud83d\udccc START HERE",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1264,
        1024
      ],
      "parameters": {
        "color": 4,
        "width": 516,
        "height": 664,
        "content": "## \ud83e\udd16 Telegram assistant with memory\n\n**Author:** **David Olusola (@DaexAI)**\n\nAI assistant that remembers conversations across sessions using MemMachine.\n\n**Features:**\n\u2705 Persistent cross-session memory\n\u2705 Voice transcription (Whisper)\n\u2705 Gmail, Sheets, Calendar tools\n\u2705 MCP architecture\n\n## How it works\n1. Message arrives (text/voice)\n2. Store in MemMachine\n3. Retrieve conversation history\n4. AI processes with context\n5. Store response & send\n\n## Setup steps\n1. Install MemMachine: `docker-compose up -d`\n2. Update org_id/project_id (nodes 4,5,9)\n3. Add credentials (Telegram, OpenAI, Google)\n4. Test with messages"
      },
      "typeVersion": 1
    },
    {
      "id": "9b2a7af6-54ea-42bb-8eab-8022659b293b",
      "name": "Voice Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        1440
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 180,
        "content": "**Voice path:** Download \u2192 Transcribe (Whisper) \u2192 Extract data"
      },
      "typeVersion": 1
    },
    {
      "id": "dd33c807-8d40-4e4d-a895-79e78c7d6cc4",
      "name": "Text Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        1680
      ],
      "parameters": {
        "color": 7,
        "height": 140,
        "content": "**Text path:** Extract message data"
      },
      "typeVersion": 1
    },
    {
      "id": "5cfcad20-0260-43e2-b2c0-14a5869f1138",
      "name": "MemMachine Memory",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        1536
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 200,
        "content": "**Memory system:** Store message \u2192 Search history (30 memories) \u2192 Sort chronologically"
      },
      "typeVersion": 1
    },
    {
      "id": "673d48ec-9108-4fe1-8cb1-1ba4ff9114db",
      "name": "AI Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        1488
      ],
      "parameters": {
        "color": 6,
        "width": 280,
        "height": 388,
        "content": "**AI + Tools:** Process with context, access Gmail/Sheets/Calendar via MCP"
      },
      "typeVersion": 1
    },
    {
      "id": "ffd7e526-7280-412e-81e5-540b820613a7",
      "name": "Response Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        1536
      ],
      "parameters": {
        "color": 3,
        "width": 716,
        "height": 232,
        "content": "**Response:** Extract \u2192 Prepare \u2192 Store in memory \u2192 Send to Telegram"
      },
      "typeVersion": 1
    },
    {
      "id": "4f2d4409-42ac-43b9-a18f-8560e5e808d3",
      "name": "MCP Architecture",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        992
      ],
      "parameters": {
        "color": 2,
        "width": 480,
        "height": 392,
        "content": "**MCP Server:** Exposes Gmail, Sheets, Calendar. **MCP Client:** Connects AI to tools"
      },
      "typeVersion": 1
    },
    {
      "id": "e162b482-4c08-4f7e-a804-c6266e846218",
      "name": "Memory Example",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        1024
      ],
      "parameters": {
        "color": 2,
        "width": 420,
        "height": 400,
        "content": "## \ud83c\udfaf Memory Example\n\n**Day 1:** \"Email john@co.com about Q1\"\n**Day 3:** \"What did I ask about John?\"\n**AI:** \"You asked me to email John about Q1 on Jan 5th\"\n\n**Day 7 (voice):** \"Follow up with John\"\n**AI:** \"I'll send follow-up to john@co.com about Q1\"\n\nAI remembers who, what, when across text & voice!"
      },
      "typeVersion": 1
    },
    {
      "id": "d20a1ce4-8ff8-4602-add3-f4349d7199e4",
      "name": "Quick Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        1024
      ],
      "parameters": {
        "color": 5,
        "width": 564,
        "height": 480,
        "content": "## \ud83d\ude80 Quick Setup\n\n**1. Install MemMachine**\n```bash\ngit clone [https://github.com/MemMachine/MemMachine](https://github.com/MemMachine/MemMachine)\ncd MemMachine\ndocker-compose up -d\n```\n\n**2. Import & Configure**\n- Import this workflow\n- Update nodes 4,5,9: org_id, project_id\n- Add credentials (Telegram, OpenAI, Google)\n\n**3. Test**\n- Text message \u2192 Check response\n- Voice message \u2192 Check transcription\n- Ask about past chats \u2192 Check memory"
      },
      "typeVersion": 1
    },
    {
      "id": "4394aac4-e55c-4d13-be11-975ce5573825",
      "name": "Customization",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        1024
      ],
      "parameters": {
        "color": 6,
        "width": 360,
        "height": 320,
        "content": "## \ud83d\udca1 Customization\n\n**Memory:** Increase top_k (node 5)\n**Tools:** Add Notion, Slack, Trello\n**Multi-channel:** WhatsApp, SMS, Web\n**AI:** Edit system prompt (node 7)\n**Advanced:** User preferences, automation"
      },
      "typeVersion": 1
    },
    {
      "id": "5cfd7a21-60e3-49de-8a27-cd2ca26cdb58",
      "name": "1. Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -1040,
        1616
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "d97b3cb4-9a24-4020-9019-91fc19616ce9",
      "name": "2. Message Type",
      "type": "n8n-nodes-base.switch",
      "position": [
        -816,
        1616
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Voice",
              "conditions": {
                "options": {
                  "version": 2
                },
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "exists"
                    },
                    "leftValue": "={{ $json.message.voice.file_id }}"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Text",
              "conditions": {
                "options": {
                  "version": 2
                },
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "exists"
                    },
                    "leftValue": "={{ $json.message.text }}"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "1eb5a7b4-92e9-41e1-951d-0f6cf2ffb053",
      "name": "3a. Download Voice",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -592,
        1520
      ],
      "parameters": {
        "fileId": "={{ $json.message.voice.file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "371ce3d2-18c8-481b-a9be-f92b789a4743",
      "name": "3b. Transcribe Voice",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -368,
        1520
      ],
      "parameters": {
        "options": {},
        "resource": "audio",
        "operation": "transcribe"
      },
      "typeVersion": 1.6
    },
    {
      "id": "29e37fd3-95fc-4339-8d06-3dba2f8b924c",
      "name": "3c. Extract Voice Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -144,
        1520
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "text",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "a2",
              "name": "chat_id",
              "type": "number",
              "value": "={{ $('1. Telegram Trigger').item.json.message.chat.id }}"
            },
            {
              "id": "a3",
              "name": "user_id",
              "type": "number",
              "value": "={{ $('1. Telegram Trigger').item.json.message.from.id }}"
            },
            {
              "id": "a4",
              "name": "username",
              "type": "string",
              "value": "={{ $('1. Telegram Trigger').item.json.message.from.username || $('1. Telegram Trigger').item.json.message.from.first_name }}"
            },
            {
              "id": "a5",
              "name": "customer_email",
              "type": "string",
              "value": "=dimejicole21@gmail.com"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b86ed0d2-be45-432f-a22a-740bf3a67fd7",
      "name": "3d. Extract Text Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -144,
        1712
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "text",
              "type": "string",
              "value": "={{ $json.message.text }}"
            },
            {
              "id": "a2",
              "name": "chat_id",
              "type": "number",
              "value": "={{ $json.message.chat.id }}"
            },
            {
              "id": "a3",
              "name": "user_id",
              "type": "number",
              "value": "={{ $json.message.from.id }}"
            },
            {
              "id": "a4",
              "name": "username",
              "type": "string",
              "value": "={{ $json.message.from.username || $json.message.from.first_name }}"
            },
            {
              "id": "a5",
              "name": "customer_email",
              "type": "string",
              "value": "=dimejicole21@gmail.com"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8485263c-d446-479e-8d74-480574dea53b",
      "name": "Unifier",
      "type": "n8n-nodes-base.code",
      "position": [
        64,
        1616
      ],
      "parameters": {
        "jsCode": "return $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "c189a91d-c337-4fe4-a3eb-d9c776b67f21",
      "name": "4. Store User Query",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        240,
        1616
      ],
      "parameters": {
        "url": "http://host.docker.internal:8080/api/v2/memories",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"org_id\": \"insuracrm\",\n  \"project_id\": \"crm-chat-v6\",\n  \"messages\": [{\n    \"content\": {{ JSON.stringify($json.text) }},\n    \"producer\": {{ JSON.stringify($json.customer_email) }},\n    \"produced_for\": \"assistant\",\n    \"role\": \"user\",\n    \"metadata\": {\n      \"customer_email\": {{ JSON.stringify($json.customer_email) }},\n      \"channel\": \"telegram\",\n      \"username\": {{ JSON.stringify($json.username) }},\n      \"user_id\": {{ JSON.stringify(String($json.user_id)) }},\n      \"timestamp\": {{ JSON.stringify($now.toISO()) }}\n    }\n  }]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "bd92e6bb-8794-49d9-8a76-076ebe2e68ee",
      "name": "5. Search Memory",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        432,
        1616
      ],
      "parameters": {
        "url": "http://host.docker.internal:8080/api/v2/memories/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"org_id\": \"insuracrm\",\n  \"project_id\": \"crm-chat-v6\",\n  \"query\": \"{{ $('Unifier').item.json.text }}\",\n  \"top_k\": 30,\n  \"filter\": \"metadata.customer_email='{{ $('Unifier').item.json.customer_email }}'\",\n  \"types\": [\"episodic\", \"semantic\"]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "8a7166f2-82c4-437e-aaed-0bf9a77955c7",
      "name": "6. Format Memory",
      "type": "n8n-nodes-base.code",
      "position": [
        608,
        1616
      ],
      "parameters": {
        "jsCode": "const memoryData = $input.first().json;\nconst episodicMemory = memoryData.content?.episodic_memory || {};\nconst longTermEpisodes = episodicMemory.long_term_memory?.episodes || [];\nconst shortTermEpisodes = episodicMemory.short_term_memory?.episodes || [];\nconst allMemories = [...longTermEpisodes, ...shortTermEpisodes];\n\nconst sortedMemories = allMemories.sort((a, b) => {\n  const timeA = a.created_at || a.metadata?.timestamp || '';\n  const timeB = b.created_at || b.metadata?.timestamp || '';\n  return new Date(timeA).getTime() - new Date(timeB).getTime();\n});\n\nconst conversationHistory = sortedMemories\n  .filter(m => m.content && m.content.trim() !== '')\n  .slice(-15)\n  .map(memory => {\n    const role = memory.producer_role || 'unknown';\n    const channel = memory.metadata?.channel || 'telegram';\n    return `[${role} via ${channel}]: ${memory.content}`;\n  }).join('\\n');\n\nconst userData = $('Unifier').first().json;\n\nreturn [{ json: { ...userData, conversation_history: conversationHistory || 'No history.', total_memories: allMemories.length } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "96f443ba-e716-4d52-bc2b-b0b4b62a57b1",
      "name": "7. AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        800,
        1616
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "options": {
          "systemMessage": "=# Role: InsuraOS Intelligence Core\nYou are the primary assistant for InsuraOS.\n\nUser: {{ $json.username }}\nCustomer: {{ $json.customer_email }}\n\n## \ud83e\udde0 Memory Context\n{{ $json.conversation_history }}\n\n## Instructions\n1. Maintain a single-room conversation feel.\n2. NEVER mention technical channel tags in the reply.\n\nTime: {{ $now }}"
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "a26d6d5b-9ecc-46a2-8bc4-8ca3944dba03",
      "name": "8. Extract Response",
      "type": "n8n-nodes-base.set",
      "position": [
        1056,
        1616
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "ai_response",
              "type": "string",
              "value": "={{ $json.output }}"
            },
            {
              "id": "a2",
              "name": "customer_email",
              "type": "string",
              "value": "={{ $('6. Format Memory').item.json.customer_email }}"
            },
            {
              "id": "a3",
              "name": "username",
              "type": "string",
              "value": "={{ $('6. Format Memory').item.json.username }}"
            },
            {
              "id": "a4",
              "name": "chat_id",
              "type": "number",
              "value": "={{ $('6. Format Memory').item.json.chat_id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "774e5725-9817-4589-827d-133e3549eaec",
      "name": "8b. Prepare for Storage",
      "type": "n8n-nodes-base.code",
      "position": [
        1200,
        1616
      ],
      "parameters": {
        "jsCode": "const inputData = $input.first().json;\nconst payload = {\n  org_id: \"insuracrm\",\n  project_id: \"crm-chat-v6\",\n  messages: [{\n    content: inputData.ai_response || '',\n    producer: \"assistant\",\n    produced_for: inputData.customer_email || '',\n    role: \"assistant\",\n    metadata: {\n      customer_email: inputData.customer_email || '',\n      channel: \"telegram\",\n      username: inputData.username || '',\n      timestamp: new Date().toISOString()\n    }\n  }]\n};\nreturn [{ json: { payload, ai_response: inputData.ai_response, chat_id: inputData.chat_id } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "09cd456b-dcbb-41fd-b45d-96314e467397",
      "name": "9. Store AI Response",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1376,
        1616
      ],
      "parameters": {
        "url": "http://host.docker.internal:8080/api/v2/memories",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify($json.payload) }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "f2f482d5-e89b-4cae-a095-fc5d1db8fdcc",
      "name": "10. Send Response",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1568,
        1616
      ],
      "parameters": {
        "text": "={{ $json.ai_response }}",
        "chatId": "={{ $json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "23bddf97-05b1-4db7-89f8-afa93f7c6d0b",
      "name": "MCP Server Trigger",
      "type": "@n8n/n8n-nodes-langchain.mcpTrigger",
      "position": [
        1264,
        1040
      ],
      "parameters": {
        "path": "298e8ee6-95f2-408b-97df-af61f48a20ec"
      },
      "typeVersion": 2
    },
    {
      "id": "5489706c-c1a5-4320-b045-2f57bb6fde4e",
      "name": "Gmail Tool",
      "type": "n8n-nodes-base.gmailTool",
      "position": [
        1200,
        1248
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "4cf74443-3727-4b9c-8ac8-94c2f3d4f4f3",
      "name": "Google Sheets Tool",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        1328,
        1248
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f4c07b00-1243-4dbe-a54b-e052edbdb9d5",
      "name": "Google Calendar Tool",
      "type": "n8n-nodes-base.googleCalendarTool",
      "position": [
        1456,
        1232
      ],
      "parameters": {
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "additionalFields": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "346e67fa-e6c0-4cd0-9ecc-cdf7df73d56f",
      "name": "MCP Client",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        896,
        1792
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "a537219d-c0bb-4dda-949b-27987e8ae5d6",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        768,
        1792
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {},
        "builtInTools": {}
      },
      "typeVersion": 1.3
    }
  ],
  "connections": {
    "Unifier": {
      "main": [
        [
          {
            "node": "4. Store User Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Tool": {
      "ai_tool": [
        [
          {
            "node": "MCP Server Trigger",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "MCP Client": {
      "ai_tool": [
        [
          {
            "node": "7. AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "7. AI Agent": {
      "main": [
        [
          {
            "node": "8. Extract Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Message Type": {
      "main": [
        [
          {
            "node": "3a. Download Voice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "3d. Extract Text Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Search Memory": {
      "main": [
        [
          {
            "node": "6. Format Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. Format Memory": {
      "main": [
        [
          {
            "node": "7. AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "7. AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "3a. Download Voice": {
      "main": [
        [
          {
            "node": "3b. Transcribe Voice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets Tool": {
      "ai_tool": [
        [
          {
            "node": "MCP Server Trigger",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "1. Telegram Trigger": {
      "main": [
        [
          {
            "node": "2. Message Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Store User Query": {
      "main": [
        [
          {
            "node": "5. Search Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8. Extract Response": {
      "main": [
        [
          {
            "node": "8b. Prepare for Storage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3b. Transcribe Voice": {
      "main": [
        [
          {
            "node": "3c. Extract Voice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9. Store AI Response": {
      "main": [
        [
          {
            "node": "10. Send Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Calendar Tool": {
      "ai_tool": [
        [
          {
            "node": "MCP Server Trigger",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "3d. Extract Text Data": {
      "main": [
        [
          {
            "node": "Unifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3c. Extract Voice Data": {
      "main": [
        [
          {
            "node": "Unifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8b. Prepare for Storage": {
      "main": [
        [
          {
            "node": "9. Store AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}