From 01169fd3daedca53ee9d0e6e773b37d49a220839 Mon Sep 17 00:00:00 2001 From: nusquama Date: Fri, 5 Dec 2025 05:00:39 +0100 Subject: [PATCH] creation --- ...with_telegram_bot_using_gpt-4o_ocr_and_voice_recognition.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 workflows/Track Expenses Automatically with Telegram Bot using GPT-4o, OCR and Voice Recognition-11368/track_expenses_automatically_with_telegram_bot_using_gpt-4o_ocr_and_voice_recognition.json diff --git a/workflows/Track Expenses Automatically with Telegram Bot using GPT-4o, OCR and Voice Recognition-11368/track_expenses_automatically_with_telegram_bot_using_gpt-4o_ocr_and_voice_recognition.json b/workflows/Track Expenses Automatically with Telegram Bot using GPT-4o, OCR and Voice Recognition-11368/track_expenses_automatically_with_telegram_bot_using_gpt-4o_ocr_and_voice_recognition.json new file mode 100644 index 000000000..354cccf68 --- /dev/null +++ b/workflows/Track Expenses Automatically with Telegram Bot using GPT-4o, OCR and Voice Recognition-11368/track_expenses_automatically_with_telegram_bot_using_gpt-4o_ocr_and_voice_recognition.json @@ -0,0 +1 @@ +{"id":"0bFdNKsZNQQP195l","meta":{"instanceId":"608063c199ef9befaee7d009cae64cabedc72960a786e69676f755ea2cde6bfa","templateCredsSetupCompleted":true},"name":"Telegram Personal Expense Tracker Agent","tags":[],"nodes":[{"id":"b591a5c7-e6f3-4a29-b73f-93ebee2c031a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1968,912],"parameters":{"color":7,"width":208,"height":304,"content":"## Message Trigger"},"typeVersion":1},{"id":"e5edd200-825e-4da0-b807-6f153acfed6c","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-2448,480],"parameters":{"width":688,"height":1472,"content":"# Personal Expense Tracker \n## Quick Start Guide\n## 1. Setup Telegram\n### 1.1 Create Telegram Bot\n - https://blog.n8n.io/create-telegram-bot/\n### 1.2 Setup Telegram Credentials for each Telegram Node: \n - Input\n - WelcomeMessage\n - GetAudioFile\n - GetAttachedFile\n - GetAttachedPhoto\n - ReplyText\n - NotAuthorizedMessage\n - DeleteProcessing\n\n## 2. Setup OpenRouter\n### 2.1 Create API Key\n - https://docs.n8n.io/integrations/builtin/credentials/openrouter/\n### 2.2 Setup AI Credentials for each AI Node: \n - Gpt4o\n - Sonnet45\n\n## 3. Setup Ainoflow\n### 3.1 Create API Key\n - https://www.ainoflow.io/signup\n### 3.2 Setup Bearer YOUR_TOKEN_HERE for each Ainoflow Node: \n - GetAppSettings\n - SaveAppSettings\n - SaveExecutionState\n - TranscribeAudio\n - ExtractFileText\n - ExtractImageText\n - TranscribeRecording\n - GetExecutionState\n - ForEachCategory\n - ForEachCategoryItem\n - DeleteItem\n### 3.3 Setup Bearer YOUR_TOKEN_HERE for MCP Tools\n - JsonStorageMcp\n\n## 4. How to use Bot\n### 4.1. Upload expense information\n - Invoice PDF\n - Image Photo\n - Any text about expense\n### 4.2. Write / Voice Chat about any additional expense\n### 4.3. Ask `Get my expenses`\n - Get by category\n - Get for previous month\n - Get for current month\n - Discuss habits\n - Ask to provide link to expense file (if available)\n\n## 5. Need customization? \n - Contact me via https://ainovasystems.com/"},"typeVersion":1},{"id":"40ad1d9c-484a-44f5-9428-80696c6f65a1","name":"Trigger","type":"n8n-nodes-base.telegramTrigger","position":[-1920,1024],"webhookId":"1597201c-8508-41e6-844a-c52c8ca302da","parameters":{"updates":["message"],"additionalFields":{"chatIds":"","userIds":"","download":true,"imageSize":"extraLarge"}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"7501af4e-cb14-47b8-ba5b-f91389a0c6a2","name":"JsonStorageMcp","type":"@n8n/n8n-nodes-langchain.mcpClientTool","position":[96,1744],"parameters":{"options":{},"endpointUrl":"https://mcp.ainoflow.io/mcp/v1/storage/json","authentication":"bearerAuth","serverTransport":"httpStreamable"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":1.1},{"id":"ff3d434c-68ec-4ff6-a790-34cbc65ee2c4","name":"Calculator","type":"@n8n/n8n-nodes-langchain.toolCalculator","position":[352,1744],"parameters":{},"typeVersion":1},{"id":"fc175bad-072b-4740-b463-08ee226383f7","name":"ExpenseAssistant","type":"@n8n/n8n-nodes-langchain.agentTool","position":[-80,1520],"parameters":{"text":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Prompt__User_Message_', ``, 'string') }}","options":{"systemMessage":"=# Expense Manager\n\n## Role\nYou manage expense recording and retrieval. You extract expense data from text or OCR, validate it, store it using MCP tools, and provide expense information.\n\n## Available MCP Tools\n\nJsonStorageMcp:\n- storage_json_create(category, data, expiresAt?, expiresMs?) - create with auto-generated key\n- storage_json_upsert(category, key, data, expiresAt?, expiresMs?) - create/update with explicit key\n- storage_json_get(category, key) - retrieve data\n- storage_json_delete(category, key) - delete data\n- storage_json_list_keys(category, page?, limit?) - list all keys in category\n\nCalculator:\n- Performs sums, averages, percentages\n\n## Allowed Expense Categories\n\nCRITICAL: Use ONLY these categories. If category not specified or unclear, use \"Other\".\n\nGroceries, Transportation, Housing, Utilities, Healthcare, Entertainment, Dining Out, Clothing, Education, Subscriptions, Personal Care, Gifts, Travel, Sports, Other\n\n## Data Storage Structure\n\nCategory in JSON Storage: YYYY-MM (year-month from expense date)\nRecord key: auto-generated by storage_json_create\n\nExpense record format:\n```json\n{\n \"id\": \"uuid\",\n \"amount\": 45.50,\n \"currency\": \"EUR\",\n \"category\": \"Groceries\",\n \"description\": \"Store name or purchase description\",\n \"date\": \"2025-11-10T14:30:00Z\",\n \"created_at\": \"2025-11-10T14:35:22Z\"\n}\n```\n\nRequired fields: id, amount (>0), currency, category (from allowed list), date, created_at\nOptional fields: description (in original document language)\n\n## Operations\n\n### 1. Add Expense\n\nCRITICAL: Add immediately without asking confirmation\n\nStep 1: Extract expense data\n- Extract amount, category, description, date, currency from text or OCR\n- If cannot extract amount → stop, inform user\n\nStep 2: Validate\n- amount > 0, category from allowed list, date valid\n- If data invalid → stop, explain the problem\n\nStep 3: Create expense\n- Generate UUID for id field\n- Call: storage_json_create(category=\"YYYY-MM\", data=expense_json)\n\nStep 4: Format response\n- Show: \"Added: *{amount} {currency}* - {category} ({description})\"\n- Show: \"Monthly total: *{total} {currency}* ({count} expenses)\"\n\nNEVER ask \"Please confirm\", \"Is this correct?\", or any confirmation questions.\n\nIf failed to extract expense:\n- \"Cannot find amount in document. Please specify amount manually.\"\n- \"Document does not contain expense information. Send a receipt or describe expense in text.\"\n\n### 2. Get Monthly Expenses\n\nDetermine period (YYYY-MM) - if not specified by user, use current month\nCall: storage_json_list_keys(category=\"YYYY-MM\")\nFor each key call: storage_json_get(category, key)\nUse Calculator for total and count\nShow summary with top expenses if many\n\n### 3. Get Expenses by Category\n\nValidate category from allowed list\nDetermine period (YYYY-MM or range) - if not specified, use current month\nGet all expenses for period\nFilter by category field\nUse Calculator for statistics\nShow results\n\n### 4. Multi-Month Statistics\n\nDetermine date range\nFor each month: storage_json_list_keys + storage_json_get\nUse Calculator for comparative statistics\nShow breakdown by months and categories\n\n### 5. Delete Expense\n\nFind expense by description/amount/date\nGet expense details\nAsk confirmation\nCall: storage_json_delete(category=\"YYYY-MM\", key)\nShow updated monthly total\n\n## Input Processing\n\n### Input Format\n\nYou ALWAYS receive text input. There are two formats:\n\n**1. Direct text from user:**\n```\nspent 50 on groceries\n```\nor just amount: \"45.50\"\nor transcribed voice: \"bought bread for 3 euros\"\n\n**2. Uploaded document/photo (prefixed format):**\n```\nUser uploaded document / photo:\n\n[optional caption from user]\n[extracted text from document/image OR error message]\n```\n\nWhen message starts with \"User uploaded document / photo:\":\n- If text is \"The uploaded file does not contain text content.\" → respond: \"Could not recognize text. Try:\\n- Upload higher quality photo\\n- Send PDF\\n- Write expense as text\"\n- Otherwise: CRITICAL! This is expense data! The text after prefix is OCR from receipt/photo or extracted text from PDF invoice. Process it and extract expense.\n\n### Data Extraction Rules\n\nFor all input:\n- Extract final total amount (after taxes/discounts)\n- Recognize date in any format, convert to ISO 8601\n- Determine category from context or vendor type\n- Create clear description from available information\n- Default currency EUR if not specified\n- Add immediately and show what was saved\n- Process content in ANY language (Russian, English, Portuguese, etc.)\n\n## Important Rules\n\nAdd expenses immediately when user provides data (text, OCR, invoice)\nVerify after action - retrieve data and confirm saved correctly\nAsk confirmation ONLY for DELETE operations\nStore in correct YYYY-MM category based on expense date\nUse Calculator for totals and statistics\nHandle any text format, date format, or currency flexibly\nDon't show technical details (storage keys, API calls) to user\n\nError handling:\n- If cannot extract amount from document → inform user clearly\n- If document doesn't contain expense → suggest solution\n- If data invalid → explain what's wrong\n- DO NOT add expense with incomplete data\n\nMultilingual:\n- Process documents and messages in ANY language\n- Keep description in original language\n- Always translate category to English (from allowed list)\n- Recognize currency names in any language\n\nFormatting:\n- Use Legacy Telegram markdown: *bold* (SINGLE asterisk) for amounts\n- NEVER use ** (double asterisk) or __ (double underscore)\n- Keep responses concise and clean\n- Don't use bullet points in responses unless user specifically asks\n\nCurrent date/time: {{ $now.toISO() }}\nCurrent storage category: {{ $now.toFormat('yyyy-MM') }}\nDefault currency: EUR\n"},"toolDescription":"AI Assitante can handle expense recording and retrieval operations."},"typeVersion":2.2},{"id":"b0269ed8-4f74-4a09-ac95-ecbec2c4fd91","name":"Gpt4o","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-160,1248],"parameters":{"model":"openai/gpt-4o","options":{}},"credentials":{"openRouterApi":{"id":"qbnEUslOR5kCNftL","name":"Openrouter"}},"typeVersion":1},{"id":"c2aad759-3504-48e4-833a-771398ff586a","name":"Think","type":"@n8n/n8n-nodes-langchain.toolThink","position":[224,1744],"parameters":{},"typeVersion":1.1},{"id":"89a37291-a019-488c-9ada-604f5460d638","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-1184,912],"parameters":{"color":2,"width":960,"height":400,"content":"## Get Chat Message / Audio Text\nDetect message type (/start, text, photo, file, audio) and route to the correct handler. \nText and audio messages are passed to the AI agent as-is.\n"},"typeVersion":1},{"id":"c245ce07-5c27-4096-8f16-85c3766a285d","name":"Switch","type":"n8n-nodes-base.switch","position":[-1136,1024],"parameters":{"rules":{"values":[{"outputKey":"start","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"2061a135-7380-4108-b565-99ebc16ac37f","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $('Trigger').item.json.message.text }}","rightValue":"/start"}]},"renameOutput":true},{"outputKey":"text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"665a9274-2939-4069-ad27-02556447d7d3","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $('Trigger').item.json.message.text }}","rightValue":""}]},"renameOutput":true},{"outputKey":"audio","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"d7360abd-5fce-4f60-832a-b7fb405255ee","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $('Trigger').item.json.message.voice.file_id }}","rightValue":""}]},"renameOutput":true},{"outputKey":"file","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"fa626c9d-b758-492b-ae44-fb6866763558","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $('Trigger').item.json.message.document.file_id }}","rightValue":""}]},"renameOutput":true},{"outputKey":"photo","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"194e3899-6a63-46db-a826-ad2768390ec5","operator":{"type":"array","operation":"exists","singleValue":true},"leftValue":"={{ $('Trigger').item.json.message.photo }}","rightValue":"photo"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.3},{"id":"197310fd-2237-414a-84a0-ec7e2fada7b3","name":"TextOutput","type":"n8n-nodes-base.set","position":[-592,976],"parameters":{"options":{},"assignments":{"assignments":[{"id":"2ee0477d-52cd-4050-86d4-5cef92b81ea8","name":"text","type":"string","value":"={{ $('Trigger').item.json.message.text }}"},{"id":"65245fe2-4dd7-4330-974b-4a0fdbbd93a4","name":"chat_id","type":"string","value":"={{ $('Trigger').item.json.message.chat.id }}"}]}},"typeVersion":3.4},{"id":"ab6e3624-de0d-4043-ba72-3e62ee120d01","name":"WelcomeMessage","type":"n8n-nodes-base.telegram","position":[-544,736],"webhookId":"9d724a96-25dd-4179-8a62-584e68cf0441","parameters":{"text":"=Hi! I'm your personal expense tracker.\n\nSend me an expense in any format, and I'll save it automatically:\n- 📝 Text: \"spent 50 on groceries\"\n- 📷 Receipt photo\n- 📄 PDF invoice\n- 🎤 Voice: \"bought bread for 3 euros\"\n\nI'll organize everything by months and categories.\n\nAsk me anytime:\n- \"How much this month?\"\n- \"Show grocery expenses\"\n- \"Compare last 3 months\"\n\nReady to track your first expense?","chatId":"={{ $('Trigger').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"7c9b6743-39ec-4195-8792-dff233a859b1","name":"AudioOutput","type":"n8n-nodes-base.set","position":[-592,1136],"parameters":{"options":{},"assignments":{"assignments":[{"id":"2ee0477d-52cd-4050-86d4-5cef92b81ea8","name":"text","type":"string","value":"={{ $json.content[0].text }}"},{"id":"dde56955-afe3-4858-bc1b-bbca9a87ee65","name":"chat_id","type":"string","value":"={{ $('Trigger').item.json.message.chat.id }}"}]}},"typeVersion":3.4},{"id":"35cd08cb-7dc2-4a5c-9454-47a9f9ce8dac","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[224,912],"parameters":{"color":4,"width":288,"height":480,"content":"## Result / Reply Message\nSends reply to the user"},"typeVersion":1},{"id":"c2ce80fa-f214-4dcc-a9bc-e182000d5125","name":"AgentInput","type":"n8n-nodes-base.set","position":[-352,1056],"parameters":{"options":{},"assignments":{"assignments":[{"id":"10b3fa10-e52d-4e80-b755-0c8310f391f3","name":"text","type":"string","value":"={{ $json.text }}"},{"id":"72a11c20-6ba3-42a7-9a01-1a032f16e2c6","name":"chat_id","type":"string","value":"={{ $json.chat_id }}"}]}},"typeVersion":3.4},{"id":"3db36880-18d1-408b-bcbf-a3578e471535","name":"NotAuthorizedMessage","type":"n8n-nodes-base.telegram","position":[-1392,1248],"webhookId":"8155dd43-d33d-47db-9fef-c9390511c80b","parameters":{"text":"=You are not authorized to use this bot.","chatId":"={{ $('Trigger').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"a4f01f8a-1317-4b4c-b447-e398702c6abf","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1760,912],"parameters":{"color":2,"width":576,"height":496,"content":"## Ensure Bot Privacy\nOn first use, the bot stores the user ID and locks access to that user. Any other user will receive an “unauthorized” message.\n"},"typeVersion":1},{"id":"17330fc2-6492-4e95-a07c-f7c6778ec66a","name":"IfAccessAllowed","type":"n8n-nodes-base.if","position":[-1376,1024],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"or","conditions":[{"id":"e3cd7b5c-eb77-451d-90a1-836353e32ab1","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $('Trigger').item.json.message.chat.id }}","rightValue":"={{ $json.chat_id ?? $('Trigger').item.json.message.chat.id }}"},{"id":"61708b93-6439-4ef4-a08c-d997f6777033","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $json.error.status }}","rightValue":404}]}},"typeVersion":2.2},{"id":"4ef7ad67-59c1-4dce-87e5-098da8cbdccc","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-624,656],"parameters":{"color":4,"width":400,"height":256,"content":"## Start Message Reply\nSend user welcome message (first use)"},"typeVersion":1},{"id":"f883ad91-ce2b-4cca-a90d-901633cbba0f","name":"IfFirstRun","type":"n8n-nodes-base.if","position":[-1712,1504],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"or","conditions":[{"id":"61708b93-6439-4ef4-a08c-d997f6777033","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $json.error.status }}","rightValue":404}]}},"typeVersion":2.2},{"id":"7de993d2-81c0-4543-93b2-4d8453c608d1","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-1760,1408],"parameters":{"color":4,"width":576,"height":288,"content":"## First Run - Save Config\nOn first use remember user chat_id to enable authorization check in future"},"typeVersion":1},{"id":"7a9d43ec-7b81-4c8e-9222-6dd190645516","name":"ReplyText","type":"n8n-nodes-base.telegram","position":[288,1056],"webhookId":"73d2d586-f3d6-45a4-ba11-32bde8fd9855","parameters":{"text":"={{ $json.output }}","chatId":"={{ $('AgentInput').item.json.chat_id }}","additionalFields":{"parse_mode":"Markdown","appendAttribution":false}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"eaf63cad-d3a8-4e15-afcf-9a77e52b0b76","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-1184,1312],"parameters":{"color":2,"width":960,"height":384,"content":"## Get Document / Photo Text\nFor photo / file upload get file content and forward to agent with appropriate prefix to make it clear that content is coming from attached file.\n"},"typeVersion":1},{"id":"99cd1c7f-0e34-47f5-8245-91410420cf6a","name":"FileOutput","type":"n8n-nodes-base.set","position":[-592,1408],"parameters":{"options":{},"assignments":{"assignments":[{"id":"2ee0477d-52cd-4050-86d4-5cef92b81ea8","name":"text","type":"string","value":"=User uploaded document / photo:\n\n{{ $('Input').item.json.message.caption ?? \"\" }}\n{{ $json.content ? $json.content[0].text : \"The uploaded file does not contain text content.\" }}"},{"id":"dde56955-afe3-4858-bc1b-bbca9a87ee65","name":"chat_id","type":"string","value":"={{ $('Trigger').item.json.message.chat.id }}"}]}},"typeVersion":3.4},{"id":"a8d8281f-20d8-4039-9977-240372e8af46","name":"GetAudioFile","type":"n8n-nodes-base.telegram","position":[-880,1136],"webhookId":"69fef630-c61f-4c66-8185-440b51d30b4b","parameters":{"fileId":"={{ $('Trigger').item.json.message.voice.file_id }}","resource":"file","additionalFields":{}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"ab30a917-2a51-4683-889a-dcb83b99e47d","name":"ExtractFileText","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-736,1408],"parameters":{"url":"https://api.ainoflow.io/api/v1/convert/submit-file","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"languages","value":"={{ $('Input').item.json.document_language }}"},{"name":"outputs","value":"text"},{"name":"response","value":"direct"},{"name":"file","parameterType":"formBinaryData","inputDataFieldName":"data"}]},"genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":true},{"id":"b7f8abf7-8a0a-4737-8ebf-bed1493b4cb1","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-224,912],"parameters":{"color":5,"width":448,"height":480,"content":"## Root Agent Processing\nMain agent responsible to forward messages to expense assistant, validate response, reject irrelevant topics, in future can be extended with more assistant connections"},"typeVersion":1},{"id":"a8a31b8b-09fc-4757-90ca-050d6ce6b90d","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-224,1392],"parameters":{"color":5,"width":736,"height":560,"content":"## Expense Assistant\nExpense assistant - handles the core logic about expenses, uses storage, calculator tools to process request"},"typeVersion":1},{"id":"3dd328b8-b601-4ff8-a3ee-aa09295aa872","name":"AssitantMemory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-48,1744],"parameters":{"sessionKey":"=expense_assitant_{{ $('AgentInput').item.json.chat_id }}","sessionIdType":"customKey"},"typeVersion":1.3},{"id":"0a183256-83ac-4e0c-9173-0affc14a6368","name":"SimpleMemory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-64,1248],"parameters":{"sessionKey":"=agent_{{ $('AgentInput').item.json.chat_id }}","sessionIdType":"customKey","contextWindowLength":30},"typeVersion":1.3},{"id":"a304ae46-8c14-423b-8ebd-3ef4ad1156d6","name":"AIAgent","type":"@n8n/n8n-nodes-langchain.agent","position":[-160,1056],"parameters":{"text":"={{ $('AgentInput').item.json.text }}","options":{"systemMessage":"=# Personal Expense Tracker\n\nYou DO NOT work with expenses directly. You call ExpenseAssistant for ALL expense requests.\n\n## Single Task\n\n1. Receive user message\n2. Pass to ExpenseAssistant WITHOUT modification\n3. Return its response\n\nCRITICAL: DO NOT extract amounts, do not reformat, do not summarize. Pass as-is.\n\n## When to Call ExpenseAssistant\n\nALWAYS call ExpenseAssistant for:\n- Any mention of spending, money, expenses\n- \"how much\", \"show\", \"expenses\"\n- ANY message starting with \"User uploaded document / photo:\" (regardless of content!)\n- Any text containing invoices, receipts, bills\n- Any numbers with currencies (EUR, USD, etc.)\n- Messages about \"does not contain text content\" or \"could not recognize\"\n\nCRITICAL: If you see \"User uploaded document / photo:\" → ALWAYS pass to ExpenseAssistant, even if there's an error!\n\n## For Non-Relevant Questions\n\n\"I'm an expense tracking assistant. I can add an expense or show statistics.\"\n\nDO NOT use this response for messages about uploaded documents!\n\n---\n\nCurrent date: {{ $now.toISO() }} \nMonth: {{ $now.toFormat('yyyy-MM') }} \nCurrency: EUR\n"},"promptType":"define"},"typeVersion":2.2},{"id":"528c64fe-cb38-40c0-b847-149ec391e413","name":"TranscribeAudio","type":"n8n-nodes-base.httpRequest","maxTries":2,"position":[-736,1136],"parameters":{"url":"https://api.ainoflow.io/api/v1/convert/submit-file","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"languages","value":"={{ $('Input').item.json.document_language }}"},{"name":"outputs","value":"text"},{"name":"response","value":"direct"},{"name":"file","parameterType":"formBinaryData","inputDataFieldName":"data"}]},"genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"retryOnFail":true,"typeVersion":4.2},{"id":"529f8d23-31c2-41d6-a721-a8a2760003c6","name":"Input","type":"n8n-nodes-base.set","position":[-1728,1024],"parameters":{"options":{},"assignments":{"assignments":[{"id":"3897ff73-577e-4e30-96bd-c043f3bc6c61","name":"document_language","type":"string","value":"={{ $json.message.from.language_code ?? \"en\" }}"}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"f7a90943-7f8e-45e5-917c-0d2a8c5acc74","name":"GetAttachedFile","type":"n8n-nodes-base.telegram","position":[-880,1408],"webhookId":"dfb04af0-28b3-42c6-a255-6994b1647b1e","parameters":{"fileId":"={{ $('Trigger').item.json.message.document.file_id }}","resource":"file","additionalFields":{}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"af85b4d7-23ee-44e8-9ae1-77c443808701","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-1184,656],"parameters":{"color":4,"width":560,"height":256,"content":"## Add processing started message\nNotify user about processing start (with message ... )"},"typeVersion":1},{"id":"3472eaa5-12ef-41c6-9562-2c430ebb0332","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-880,1696],"parameters":{"color":4,"width":656,"height":256,"content":"## Remove processing message\nAfter processing is complete, this part deletes temporary \"processing\" (\"...\") message"},"typeVersion":1},{"id":"3be5a7aa-b70e-4143-af04-cf0b3984ba36","name":"IfStateExist","type":"n8n-nodes-base.if","position":[-624,1792],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"c5e9f88f-3726-43a4-9394-7b2b0a95b544","operator":{"type":"number","operation":"exists","singleValue":true},"leftValue":"={{ $json.chat_id }}","rightValue":""},{"id":"24d6e488-9735-49bb-af52-a84fcbfbde8c","operator":{"type":"number","operation":"exists","singleValue":true},"leftValue":"={{ $json.message_id }}","rightValue":""}]}},"typeVersion":2.2},{"id":"96232073-4006-42f3-b19b-9ce30853f1f9","name":"DeleteProcessing","type":"n8n-nodes-base.telegram","position":[-384,1792],"webhookId":"e48603f5-dfa0-48ae-9430-12bf943d31e5","parameters":{"chatId":"={{ $json.chat_id }}","messageId":"={{ $json.message_id }}","operation":"deleteMessage"},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"8d890581-cfe2-4b0e-b6ee-732978b0d697","name":"Think1","type":"@n8n/n8n-nodes-langchain.toolThink","position":[48,1248],"parameters":{},"typeVersion":1.1},{"id":"aef6541d-fcde-49e8-80af-63f23509bdbe","name":"Cleanup","type":"n8n-nodes-base.manualTrigger","position":[-1696,1792],"parameters":{},"typeVersion":1},{"id":"f57b4394-872c-44a0-96e9-c2990ec22447","name":"ForEachCategory","type":"n8n-nodes-base.httpRequest","onError":"continueErrorOutput","position":[-1504,1792],"parameters":{"url":"https://api.ainoflow.io/api/v1/storage/json","options":{},"authentication":"genericCredentialType","genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":false},{"id":"0077379d-2fda-451e-8b6c-1d8045d8c2db","name":"ForEachCategoryItem","type":"n8n-nodes-base.httpRequest","onError":"continueErrorOutput","position":[-1296,1792],"parameters":{"url":"=https://api.ainoflow.io/api/v1/storage/json/{{ $json.category }}","options":{},"authentication":"genericCredentialType","genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":false},{"id":"e09b5aa4-e64d-415b-8e18-f08aa005a98c","name":"DeleteItem","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-1072,1792],"parameters":{"url":"=https://api.ainoflow.io/api/v1/storage/json/{{ $json.category }}/{{ $json.key }}","method":"DELETE","options":{},"authentication":"genericCredentialType","genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":false},{"id":"73a49d7e-ae53-4dfb-863a-e696b1c95485","name":"GetAttachedPhoto","type":"n8n-nodes-base.telegram","position":[-880,1536],"webhookId":"dfb04af0-28b3-42c6-a255-6994b1647b1e","parameters":{"fileId":"={{ $('Trigger').item.json.message.photo[$('Trigger').item.json.message.photo.length-1].file_id }}","resource":"file","additionalFields":{}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"a1fc3d64-ddf8-402c-b60f-a9e022f2f17d","name":"ImageOutput","type":"n8n-nodes-base.set","position":[-592,1536],"parameters":{"options":{},"assignments":{"assignments":[{"id":"2ee0477d-52cd-4050-86d4-5cef92b81ea8","name":"text","type":"string","value":"=User uploaded document / photo:\n\n{{ $('Input').item.json.message.caption ?? \"\" }}\n{{ $json.content ? $json.content[0].text : \"The uploaded file does not contain text content.\" }}"},{"id":"dde56955-afe3-4858-bc1b-bbca9a87ee65","name":"chat_id","type":"string","value":"={{ $('Trigger').item.json.message.chat.id }}"}]}},"typeVersion":3.4},{"id":"9e7fa633-a3d5-4de1-b8b7-f056090069bf","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","disabled":true,"position":[-1760,1696],"parameters":{"color":7,"width":880,"height":256,"content":"## Cleanup / Reset\nThis is **MANUAL** trigger to full data cleanup. **Warning - this will DELETE ALL DATA** stored in your **Ainoflow** account"},"typeVersion":1},{"id":"424964de-61df-4f24-97a4-ae6f5d74b478","name":"ExtractImageText","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-736,1536],"parameters":{"url":"https://api.ainoflow.io/api/v1/convert/submit-file","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"languages","value":"={{ $('Input').item.json.document_language }}"},{"name":"outputs","value":"text"},{"name":"response","value":"direct"},{"name":"file","parameterType":"formBinaryData","inputDataFieldName":"data"},{"name":"models","value":"paddleocr"}]},"genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":true},{"id":"8272ec82-344c-4769-91ac-ccebce125777","name":"SendProcessing","type":"n8n-nodes-base.telegram","position":[-1104,752],"webhookId":"77b9f445-8eae-4017-8490-0f61a6783d43","parameters":{"text":"=...","chatId":"={{ $('Trigger').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"etQHUkjTFalk8bG0","name":"AinoflowExpenses"}},"typeVersion":1.2},{"id":"90dc3683-4e85-4c79-a44d-52f04e2d6e39","name":"GetExecutionState","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-816,1792],"parameters":{"url":"=https://api.ainoflow.io/api/v1/storage/json/expense-app-processing/{{ $('Trigger').item.json.update_id }}","options":{},"authentication":"genericCredentialType","genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":true},{"id":"bf8eec4b-64b7-4580-840b-f2d910e949b7","name":"Sonnet45","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-176,1744],"parameters":{"model":"anthropic/claude-sonnet-4.5","options":{}},"credentials":{"openRouterApi":{"id":"qbnEUslOR5kCNftL","name":"Openrouter"}},"typeVersion":1},{"id":"9cd45908-6cb1-499a-9e8c-95f4cc69e4e5","name":"GetAppSettings","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-1552,1024],"parameters":{"url":"https://api.ainoflow.io/api/v1/storage/json/config/expense-app-settings","options":{},"authentication":"genericCredentialType","genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2,"alwaysOutputData":true},{"id":"a5ed9d9e-8fb1-4fba-8537-d4fe91932517","name":"SaveAppSettings","type":"n8n-nodes-base.httpRequest","position":[-1488,1488],"parameters":{"url":"https://api.ainoflow.io/api/v1/storage/json/config/expense-app-settings","method":"PUT","options":{},"sendBody":true,"authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"chat_id","value":"={{ $('Trigger').item.json.message.chat.id }}"},{"name":"start_date","value":"={{ $('Trigger').item.json.message.date }}"},{"name":"first_name","value":"={{ $('Trigger').item.json.message.chat.first_name }}"}]},"genericAuthType":"httpBearerAuth"},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2},{"id":"e6b007bf-589a-46b4-ae5e-0f0ae88bcd17","name":"SaveExecutionState","type":"n8n-nodes-base.httpRequest","position":[-912,752],"parameters":{"url":"=https://api.ainoflow.io/api/v1/storage/json/expense-app-processing/{{ $('Trigger').item.json.update_id }}","method":"PUT","options":{},"sendBody":true,"sendQuery":true,"authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"chat_id","value":"={{ $json.result.chat.id }}"},{"name":"message_id","value":"={{ $json.result.message_id }}"}]},"genericAuthType":"httpBearerAuth","queryParameters":{"parameters":[{"name":"expiresMs","value":"3600000"}]}},"credentials":{"httpBearerAuth":{"id":"CdhQVxeD79PpCCOL","name":"AinoflowPrimary"}},"typeVersion":4.2}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"50b5551e-ef7d-4590-81d0-37339c1a8794","connections":{"Gpt4o":{"ai_languageModel":[[{"node":"AIAgent","type":"ai_languageModel","index":0}]]},"Input":{"main":[[{"node":"GetAppSettings","type":"main","index":0}]]},"Think":{"ai_tool":[[{"node":"ExpenseAssistant","type":"ai_tool","index":0}]]},"Switch":{"main":[[{"node":"WelcomeMessage","type":"main","index":0}],[{"node":"TextOutput","type":"main","index":0}],[{"node":"GetAudioFile","type":"main","index":0}],[{"node":"GetAttachedFile","type":"main","index":0}],[{"node":"GetAttachedPhoto","type":"main","index":0}]]},"Think1":{"ai_tool":[[{"node":"AIAgent","type":"ai_tool","index":0}]]},"AIAgent":{"main":[[{"node":"ReplyText","type":"main","index":0}]]},"Cleanup":{"main":[[{"node":"ForEachCategory","type":"main","index":0}]]},"Trigger":{"main":[[{"node":"Input","type":"main","index":0}]]},"Sonnet45":{"ai_languageModel":[[{"node":"ExpenseAssistant","type":"ai_languageModel","index":0}]]},"AgentInput":{"main":[[{"node":"AIAgent","type":"main","index":0}]]},"Calculator":{"ai_tool":[[{"node":"ExpenseAssistant","type":"ai_tool","index":0}]]},"FileOutput":{"main":[[{"node":"AgentInput","type":"main","index":0}]]},"IfFirstRun":{"main":[[{"node":"SaveAppSettings","type":"main","index":0}]]},"TextOutput":{"main":[[{"node":"AgentInput","type":"main","index":0}]]},"AudioOutput":{"main":[[{"node":"AgentInput","type":"main","index":0}]]},"ImageOutput":{"main":[[{"node":"AgentInput","type":"main","index":0}]]},"GetAudioFile":{"main":[[{"node":"TranscribeAudio","type":"main","index":0}]]},"IfStateExist":{"main":[[{"node":"DeleteProcessing","type":"main","index":0}]]},"SimpleMemory":{"ai_memory":[[{"node":"AIAgent","type":"ai_memory","index":0}]]},"AssitantMemory":{"ai_memory":[[{"node":"ExpenseAssistant","type":"ai_memory","index":0}]]},"GetAppSettings":{"main":[[{"node":"IfFirstRun","type":"main","index":0},{"node":"IfAccessAllowed","type":"main","index":0}]]},"JsonStorageMcp":{"ai_tool":[[{"node":"ExpenseAssistant","type":"ai_tool","index":0}]]},"SendProcessing":{"main":[[{"node":"SaveExecutionState","type":"main","index":0}]]},"ExtractFileText":{"main":[[{"node":"FileOutput","type":"main","index":0}]]},"ForEachCategory":{"main":[[{"node":"ForEachCategoryItem","type":"main","index":0}]]},"GetAttachedFile":{"main":[[{"node":"ExtractFileText","type":"main","index":0}]]},"IfAccessAllowed":{"main":[[{"node":"Switch","type":"main","index":0},{"node":"SendProcessing","type":"main","index":0},{"node":"GetExecutionState","type":"main","index":0}],[{"node":"NotAuthorizedMessage","type":"main","index":0}]]},"TranscribeAudio":{"main":[[{"node":"AudioOutput","type":"main","index":0}]]},"ExpenseAssistant":{"ai_tool":[[{"node":"AIAgent","type":"ai_tool","index":0}]]},"ExtractImageText":{"main":[[{"node":"ImageOutput","type":"main","index":0}]]},"GetAttachedPhoto":{"main":[[{"node":"ExtractImageText","type":"main","index":0}]]},"GetExecutionState":{"main":[[{"node":"IfStateExist","type":"main","index":0}]]},"ForEachCategoryItem":{"main":[[{"node":"DeleteItem","type":"main","index":0}]]}}} \ No newline at end of file