{ "id": "1lIKvVJQIcva30YM", "name": "πŸ“¬ Gmail β€” Daily Digest [Schedule]", "nodes": [ { "parameters": { "rule": { "interval": [ { "field": "hours", "hoursInterval": 3 } ] } }, "id": "85c1a689-35df-4b58-bab4-478b11c880af", "name": "⏰ Ogni 3 ore", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ -1824, 48 ] }, { "parameters": { "resource": "label" }, "id": "a3e97bde-9106-4254-b49d-a164b5fa8cfd", "name": "Gmail - Leggi tutte le label", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ -1568, 144 ], "webhookId": "9959425d-bdbb-4597-ad72-77ec25fcf49c", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "labels", "options": {} }, "id": "a7ae3604-c2e6-4182-b89e-c9667217e86f", "name": "Aggrega Label", "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ -1376, 144 ] }, { "parameters": { "operation": "getAll", "limit": 20, "filters": { "q": "-label:Processed newer_than:1d", "readStatus": "unread" } }, "id": "b73f8915-1173-43a8-9f78-0c49fa471b7d", "name": "Gmail - Fetch ultime 3h", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ -1008, 304 ], "webhookId": "efc020f5-87c1-4009-8bc2-82ad371c0dde", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "operation": "get", "messageId": "={{ $json.id }}" }, "id": "157667ee-6539-40c2-b826-d6abf7fe945c", "name": "Gmail - Leggi contenuto", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ -736, -32 ], "webhookId": "078abbbb-a75c-4507-8c0a-23196b1fef45", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "emails", "options": {} }, "id": "153d3836-9028-4838-8cdc-4281d6531cc5", "name": "Aggrega Email", "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ -512, -32 ] }, { "parameters": { "jsCode": "const item = $input.first();\nconst emailsRaw = item.json.emails || [];\nconst emails = emailsRaw.map(e => e.json || e);\n\nif (emails.length === 0) {\n return [{ json: { prompt: 'NESSUNA_EMAIL', emailCount: 0, emailMeta: [] } }];\n}\n\nconst emailMeta = emails.map(e => ({ id: e.id, threadId: e.threadId || e.id }));\n\nconst threads = {};\nemails.forEach(e => {\n const tid = e.threadId || e.id;\n if (!threads[tid]) threads[tid] = [];\n threads[tid].push(e.id);\n});\n\nconst emailList = emails.map((e, i) => {\n const from = e.From || e.from || 'Mittente sconosciuto';\n const subject = e.Subject || e.subject || '(nessun oggetto)';\n const date = e.Date || e.date || '';\n const body = (e.text || e.snippet || '').substring(0, 600);\n // Gmail node restituisce payload.mimeType='multipart/mixed' quando ci sono allegati\n const hasMixedPayload = e.payload && e.payload.mimeType === 'multipart/mixed';\n const hasAtt = (hasMixedPayload || (e.attachments && e.attachments.length > 0)) ? 'SΓ¬ (PDF probabile)' : 'No';\n const threadCount = (threads[e.threadId || e.id] || []).length;\n const threadNote = threadCount > 1 ? ` [THREAD: ${threadCount} msg]` : '';\n return `--- EMAIL ${i + 1}${threadNote} ---\nID: ${e.id}\nThreadID: ${e.threadId || e.id}\nDa: ${from}\nOggetto: ${subject}\nData: ${date}\nAllegati: ${hasAtt}\n${body}`;\n}).join('\\n\\n');\n\nconst today = new Date().toLocaleDateString('it-IT', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'\n});\n\nconst prompt = `Sei l'assistente personale di Martin. Analizza ${emails.length} email non lette.\n\nLABEL GMAIL (nomi ESATTI, rispetta maiuscole e &):\nLavoro/Comunicazioni, Lavoro/Cedolino, Lavoro/Contratto\nCondominio/Comunicazioni, Condominio/Spese\nInternet/Bollette, Internet/Comunicazioni\nLuce&Gas/Bollette, Luce&Gas/Comunicazioni\nMarketing, Prenotazioni\nRicevute/Trasporti, Ricevute/Acquisti, Ricevute/Abbonamenti\n\nREGOLE CLASSIFICAZIONE:\n- action \"trash\" solo per Marketing/newsletter β†’ verranno eliminate automaticamente\n- action \"keep\" per tutto il resto β†’ etichettate e incluse nel report\n- EMAIL con stesso ThreadID = stessa conversazione: riassumile INSIEME nel report\n- Non usare label non presenti nella lista sopra\n\nPAPERLESS ACTION (campo aggiuntivo, guarda il campo Allegati):\n- paperless_action \"pdf_allegato\" β†’ email con allegato PDF che potrebbe valere la pena archiviare (Allegati: SΓ¬) β€” bollette, ricevute, contratti, cedolini, comunicazioni ufficiali, etc.\n- paperless_action null β†’ email senza allegati PDF rilevanti, o allegati irrilevanti (immagini, firma, etc.)\n\nREPORT (daily_report) - OBBLIGATORIO essere narrativo:\n- Scrivi come un assistente personale che racconta a Martin cosa c'Γ¨ nella sua inbox\n- NON fare semplice elenco mittente/oggetto: racconta cosa Γ¨ successo\n- Raggruppa thread correlati in un unico punto\n- Estrai dettagli concreti: importi €, date, numeri ordine, azioni richieste\n- Segnala esplicitamente se Martin deve fare qualcosa\n- Ordine: urgente/da rispondere, poi info utili, poi ricevute, poi eliminati\n- Usa *grassetto* e emoji Telegram. Max 3000 caratteri.\n\nRispondi SOLO JSON valido:\n{\n \"emails\": [\n {\"id\": \"ID_ESATTO\", \"action\": \"trash\", \"labels\": [\"Marketing\"], \"summary\": \"\", \"paperless_action\": null},\n {\"id\": \"ID_ESATTO\", \"action\": \"keep\", \"labels\": [\"Luce&Gas/Bollette\"], \"summary\": \"E.ON €87,50 scad. 28/03\", \"paperless_action\": \"pdf_allegato\"},\n {\"id\": \"ID_ESATTO\", \"action\": \"keep\", \"labels\": [\"Internet/Bollette\"], \"summary\": \"Avviso bolletta Fastweb disponibile\", \"paperless_action\": null}\n ],\n \"daily_report\": \"[REPORT NARRATIVO]\"\n}\n\n${emailList}`;\n\nreturn [{ json: { prompt, emailCount: emails.length, emailMeta } }];" }, "id": "f6b052dd-48da-41dd-8c68-f58c8b9f8c1d", "name": "Costruisci Prompt", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -288, -32 ] }, { "parameters": { "jsCode": "const raw = $input.first().json;\n// Formato OpenAI: choices[0].message.content\nconst rawText = (raw.choices && raw.choices[0] && raw.choices[0].message)\n ? raw.choices[0].message.content\n : (raw.text || raw.output || '');\n\nconst cleaned = rawText\n .replace(/[\\s\\S]*?<\\/thinking>/gi, '')\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n\nlet parsed;\ntry {\n parsed = JSON.parse(cleaned);\n} catch (e) {\n const match = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n try { parsed = JSON.parse(match[0]); }\n catch (e2) { throw new Error('Parse error: ' + rawText.substring(0, 300)); }\n } else {\n throw new Error('No JSON found: ' + rawText.substring(0, 300));\n }\n}\n\nif (!parsed.emails || !Array.isArray(parsed.emails)) {\n throw new Error('Missing emails array: ' + JSON.stringify(parsed).substring(0, 200));\n}\n\nconst emailMeta = $('Costruisci Prompt').first().json.emailMeta || [];\nconst metaMap = {};\nemailMeta.forEach(m => { metaMap[m.id] = m.threadId; });\n\nparsed.emails = parsed.emails.map(e => ({\n ...e,\n threadId: metaMap[e.id] || e.id\n}));\n\nreturn [{ json: parsed }];" }, "id": "cac1efac-2d3e-482c-a529-22bdd2136575", "name": "Parse risposta GPT-4.1", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 432, -32 ] }, { "parameters": { "chatId": "-4814221197", "text": "={{ $json.daily_report }}", "additionalFields": { "parse_mode": "Markdown" } }, "id": "1855e5cf-9dfb-4b81-9f1a-72d2d8a546a0", "name": "Telegram - Invia Report", "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [ 704, -192 ], "webhookId": "d42335fd-4748-4406-b0dd-d8d7f4d0b027", "credentials": { "telegramApi": { "id": "uTXHLqcCJxbOvqN3", "name": "Telegram account" } } }, { "parameters": { "fieldToSplitOut": "emails", "options": {} }, "id": "a0502f51-c43d-4792-8bf1-f5a95d592562", "name": "Dividi Email", "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 704, 96 ] }, { "parameters": { "conditions": { "string": [ { "value1": "={{ $json.action }}", "value2": "trash" } ] } }, "id": "dec6cf2a-7254-4496-a24f-be4a0070eb0f", "name": "È da eliminare?", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [ 944, 96 ] }, { "parameters": { "operation": "markAsRead", "messageId": "={{ $json.id }}" }, "id": "3c5a7e25-08df-4620-afc7-fbbdf5e5730c", "name": "Gmail - Segna come letta", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1200, -80 ], "webhookId": "abc3390b-9a83-4a40-bf36-d52a921a25b0", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "resource": "thread", "operation": "trash", "threadId": "={{ $json.threadId }}" }, "id": "e3fdcf0f-c55b-40d9-a99a-a665db028895", "name": "Gmail - Sposta nel cestino", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1488, -80 ], "webhookId": "e0919d48-248a-4191-b8ca-6f9ff619bf16", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "jsCode": "const items = $input.all();\nif (items.length === 0) return [];\n\n// Costruisce mappa nome β†’ ID dalle label Gmail\nconst labelsData = $('Gmail - Leggi tutte le label').all();\nconst labelMap = {};\nlabelsData.forEach(item => {\n const name = item.json.name;\n const id = item.json.id;\n if (name && id) labelMap[name] = id;\n});\n\n// Processa ogni email nella branch \"keep\"\nconst result = [];\nfor (const item of items) {\n const email = item.json;\n const requestedLabels = Array.isArray(email.labels) ? email.labels : [];\n const resolvedLabelIds = requestedLabels\n .map(name => labelMap[name])\n .filter(id => !!id);\n\n // Skip se nessuna label trovata (evita errore Gmail 'No label add or removes')\n if (resolvedLabelIds.length === 0) continue;\n\n result.push({\n json: {\n id: String(email.id || ''),\n threadId: String(email.threadId || email.id || ''),\n action: String(email.action || 'keep'),\n labels: requestedLabels,\n summary: String(email.summary || ''),\n resolvedLabelIds: resolvedLabelIds\n }\n });\n}\n\nreturn result;" }, "id": "99e0b420-3d9a-4ece-80ed-27dab248b018", "name": "Risolvi ID Label", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1504, 368 ] }, { "parameters": { "operation": "addLabels", "messageId": "={{ $json.id }}", "labelIds": "={{ $json.resolvedLabelIds }}" }, "id": "29b7cc48-03a5-45d3-a94a-dbeae0710f7b", "name": "Gmail - Aggiungi Label", "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1696, 368 ], "webhookId": "debadb11-9b5c-44a6-9ad0-7f1a6598b14a", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "path": "gmail-digest-test", "options": {} }, "id": "test-webhook-trigger", "name": "πŸ§ͺ Test Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [ -1824, -112 ], "webhookId": "gmail-digest-test-001" }, { "parameters": { "method": "POST", "url": "https://api.githubcopilot.com/chat/completions", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Authorization", "value": "={{ 'Bearer ' + $('Ottieni Token Copilot').first().json.token }}" }, { "name": "Content-Type", "value": "application/json" }, { "name": "Copilot-Integration-Id", "value": "vscode-chat" }, { "name": "Editor-Version", "value": "vscode/1.85.0" } ] }, "sendBody": true, "contentType": "raw", "rawContentType": "application/json", "body": "={{ JSON.stringify({\"model\":\"gpt-4.1\",\"messages\":[{\"role\":\"system\",\"content\":\"Rispondi SOLO con JSON valido.\"},{\"role\":\"user\",\"content\": $('Costruisci Prompt').first().json.prompt}],\"response_format\":{\"type\":\"json_object\"},\"max_tokens\":8192}) }}", "options": {} }, "id": "copilot-gpt41-node", "name": "GPT-4.1 - Classifica Email", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 192, -32 ] }, { "parameters": { "url": "https://api.github.com/copilot_internal/v2/token", "authentication": "predefinedCredentialType", "nodeCredentialType": "httpHeaderAuth", "options": {} }, "id": "copilot-token-refresh", "name": "Ottieni Token Copilot", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ -64, -32 ], "credentials": { "httpHeaderAuth": { "id": "vBwUxlzKrX3oDHyN", "name": "GitHub Copilot OAuth Token" } } }, { "parameters": { "conditions": { "options": { "leftValue": "", "caseSensitive": true, "typeValidation": "loose" }, "combinator": "and", "conditions": [ { "id": "p1", "leftValue": "={{ Boolean($json.paperless_action) }}", "operator": { "type": "boolean", "operation": "true" }, "rightValue": "" } ] }, "options": {} }, "id": "if-paperless", "name": "Ha azione Paperless?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 1200, 272 ] }, { "parameters": { "conditions": { "options": {}, "combinator": "and", "conditions": [ { "id": "b1", "leftValue": "={{ $json.paperless_action }}", "operator": { "type": "string", "operation": "equals" }, "rightValue": "pdf_allegato" } ] }, "options": {} }, "id": "if-bolletta-or-fastweb", "name": "Ha PDF allegato?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 1488, 112 ] }, { "parameters": { "jsCode": "// Leggi il messaggio Gmail completo per trovare gli allegati PDF\n// Il nodo Gmail - Leggi contenuto ha giΓ  il payload completo\nconst emails = $input.all();\nconst results = [];\nfor (const emailItem of emails) {\n const email = emailItem.json;\n if (email.paperless_action !== 'pdf_allegato') continue;\n // Trova allegati PDF in payload.parts (ricorsivo)\n function findPDFs(parts, found) {\n if (!parts) return;\n for (const p of parts) {\n if (p.parts) findPDFs(p.parts, found);\n if (p.body && p.body.attachmentId) {\n const isPDF = (p.mimeType||'').includes('pdf') || (p.filename||'').toLowerCase().endsWith('.pdf');\n if (isPDF) found.push({ attachment_id: p.body.attachmentId, filename: p.filename || 'documento.pdf' });\n }\n }\n }\n const pdfs = [];\n findPDFs((email.payload && email.payload.parts) || [], pdfs);\n for (const pdf of pdfs) {\n results.push({ json: {\n email_id: email.id,\n attachment_id: pdf.attachment_id,\n filename: pdf.filename,\n hint: (email.Subject || email.subject || '') + ' da ' + (email.From || email.from || ''),\n from: email.From || email.from || '',\n }});\n }\n}\nreturn results;" }, "id": "http-trigger-bolletta", "name": "Estrai Allegati PDF", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1824, -16 ] }, { "parameters": { "conditions": { "options": {}, "combinator": "and", "conditions": [ { "id": "t1", "leftValue": "={{ $('πŸ§ͺ Test Webhook').isExecuted }}", "operator": { "type": "boolean", "operation": "true" } } ] }, "options": {} }, "id": "if-is-test", "name": "È un test?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ -1184, 144 ] }, { "parameters": { "operation": "getAll", "limit": 20, "filters": { "q": "-label:Processed newer_than:1d", "readStatus": "unread" } }, "id": "gmail-fetch-all-unread", "name": "Gmail - Fetch tutte non lette", "type": "n8n-nodes-base.gmail", "typeVersion": 2.1, "position": [ -992, -32 ], "webhookId": "94c9342a-4f54-42f1-9f8f-4a165468ba33", "credentials": { "gmailOAuth2": { "id": "qvOikS6IF0H5khr8", "name": "Gmail account" } } }, { "parameters": { "method": "POST", "url": "https://orchestrator.mt-home.uk/webhook/paperless-upload", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ email_id: $json.email_id, attachment_id: $json.attachment_id, filename: $json.filename, hint: $json.hint, from: $json.from }) }}", "options": {} }, "id": "n_callcore", "name": "Chiama Core Upload", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 2160, 128 ] }, { "id": "n_estrai_fatti", "name": "🧠 Estrai Fatti", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1900, 400 ], "parameters": { "jsCode": "const parsed = $input.first().json;\nconst copilotToken = $('Ottieni Token Copilot').first().json.token;\n\n// Only non-trash emails with a summary\nconst keepEmails = (parsed.emails || []).filter(e => e.action !== 'trash' && e.summary?.trim());\nif (keepEmails.length === 0) return [{ json: { _skip: true } }];\n\nconst emailList = keepEmails.map((e, i) =>\n `${i+1}. [labels: ${(e.labels||[]).join(',')}] [threadId: ${e.threadId}]\\nRiassunto: ${e.summary}`\n).join('\\n\\n');\n\nconst gptRes = await this.helpers.httpRequest({\n method: 'POST',\n url: 'https://api.githubcopilot.com/chat/completions',\n headers: {\n 'Authorization': `Bearer ${copilotToken}`,\n 'editor-version': 'vscode/1.95.3',\n 'Copilot-Integration-Id': 'vscode-chat',\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n model: 'gpt-4.1',\n messages: [\n { role: 'system', content: 'Sei un assistente che estrae fatti strutturati da email per il sistema di memoria di Pompeo, l\\'AI personale di Martin Tahiraj. Rispondi SEMPRE con JSON valido.' },\n { role: 'user', content: `Estrai un fatto strutturato per ogni email che Martin ha ricevuto oggi.\n\nEMAIL (indice. [label] [threadId]):\n${emailList}\n\nRegole TTL:\n- Prenotazioni, viaggi, eventi imminenti β†’ ttl_days: 14\n- Bollette β†’ ttl_days: 45\n- Lavoro, condominio, documenti ufficiali β†’ ttl_days: 90\n- Abbonamenti, acquisti β†’ ttl_days: 30\n- Default β†’ ttl_days: 30\n\nRispondi SOLO JSON:\n{\n \"facts\": [\n {\n \"index\": 1,\n \"thread_id\": \"threadId_esatto\",\n \"category\": \"finance|work|home|personal|travel|subscription|health\",\n \"subject\": \"fatto conciso max 120 caratteri\",\n \"detail\": {\"from\": \"mittente\", \"labels\": [\"label1\"]},\n \"action_required\": false,\n \"action_text\": \"\",\n \"pompeo_note\": \"inner monologue breve: perchΓ© questo fatto Γ¨ rilevante per capire Martin o la sua vita\",\n \"entity_refs\": {\"people\": [], \"places\": [], \"products\": [], \"amounts\": []},\n \"ttl_days\": 30\n }\n ]\n}` }\n ],\n temperature: 0.2,\n response_format: { type: 'json_object' }\n })\n});\n\nconst content = gptRes.choices?.[0]?.message?.content || '{}';\nconst { facts = [] } = JSON.parse(content);\n\nconst now = new Date();\nconst results = facts.map(f => {\n const email = keepEmails[f.index - 1] || keepEmails.find(e => e.threadId === f.thread_id);\n if (!f.thread_id && !email?.threadId) return null;\n const expiresAt = (f.ttl_days > 0)\n ? new Date(now.getTime() + f.ttl_days * 86400000).toISOString()\n : null;\n const detail = JSON.stringify({ ...(f.detail || {}), labels: email?.labels || [] });\n return { json: {\n thread_id: f.thread_id || email?.threadId,\n category: f.category || 'personal',\n subject: (f.subject || email?.summary || '').substring(0, 200).replace(/'/g, \"''\"),\n detail,\n action_required: f.action_required ? true : false,\n action_text: (f.action_text || '').replace(/'/g, \"''\"),\n pompeo_note: (f.pompeo_note || '').replace(/'/g, \"''\"),\n entity_refs: JSON.stringify(f.entity_refs || {}),\n expires_at: expiresAt\n }};\n}).filter(Boolean);\n\nreturn results.length > 0 ? results : [{ json: { _skip: true } }];" } }, { "id": "n_if_skip", "name": "πŸ”€ Ha Fatti?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 2120, 400 ], "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "cond_skip", "leftValue": "={{ $json._skip }}", "rightValue": true, "operator": { "type": "boolean", "operation": "notEquals" } } ], "combinator": "and" } } }, { "id": "n_upsert_memoria", "name": "πŸ’Ύ Upsert Memoria", "type": "n8n-nodes-base.postgres", "typeVersion": 2.5, "position": [ 2340, 400 ], "credentials": { "postgres": { "id": "mRqzxhSboGscolqI", "name": "Pompeo β€” PostgreSQL" } }, "parameters": { "operation": "executeQuery", "query": "INSERT INTO memory_facts\n (user_id, source, source_ref, category, subject, detail, action_required, action_text, pompeo_note, entity_refs, expires_at)\nVALUES (\n 'martin',\n 'email',\n '{{ $json.thread_id }}',\n '{{ $json.category }}',\n '{{ $json.subject }}',\n '{{ $json.detail }}',\n {{ $json.action_required }},\n '{{ $json.action_text }}',\n '{{ $json.pompeo_note }}',\n '{{ $json.entity_refs }}'::jsonb,\n {{ $json.expires_at ? \"'\" + $json.expires_at + \"'::timestamptz\" : \"NULL\" }}\n)\nON CONFLICT (user_id, source, source_ref) WHERE source_ref IS NOT NULL DO UPDATE SET\n subject = EXCLUDED.subject,\n detail = EXCLUDED.detail,\n action_required = EXCLUDED.action_required,\n action_text = EXCLUDED.action_text,\n pompeo_note = EXCLUDED.pompeo_note,\n entity_refs = EXCLUDED.entity_refs,\n expires_at = EXCLUDED.expires_at", "options": {} } } ], "connections": { "Gmail - Leggi tutte le label": { "main": [ [ { "node": "Aggrega Label", "type": "main", "index": 0 } ] ] }, "Aggrega Label": { "main": [ [ { "node": "È un test?", "type": "main", "index": 0 } ] ] }, "Gmail - Leggi contenuto": { "main": [ [ { "node": "Aggrega Email", "type": "main", "index": 0 } ] ] }, "Aggrega Email": { "main": [ [ { "node": "Costruisci Prompt", "type": "main", "index": 0 } ] ] }, "Dividi Email": { "main": [ [ { "node": "È da eliminare?", "type": "main", "index": 0 } ] ] }, "È da eliminare?": { "main": [ [ { "node": "Gmail - Segna come letta", "type": "main", "index": 0 } ], [ { "node": "Ha azione Paperless?", "type": "main", "index": 0 } ] ] }, "Gmail - Segna come letta": { "main": [ [ { "node": "Gmail - Sposta nel cestino", "type": "main", "index": 0 } ] ] }, "Risolvi ID Label": { "main": [ [ { "node": "Gmail - Aggiungi Label", "type": "main", "index": 0 } ] ] }, "Costruisci Prompt": { "main": [ [ { "node": "Ottieni Token Copilot", "type": "main", "index": 0 } ] ] }, "πŸ§ͺ Test Webhook": { "main": [ [ { "node": "Gmail - Leggi tutte le label", "type": "0", "index": 0 } ] ] }, "GPT-4.1 - Classifica Email": { "main": [ [ { "node": "Parse risposta GPT-4.1", "type": "main", "index": 0 } ] ] }, "Parse risposta GPT-4.1": { "main": [ [ { "node": "Telegram - Invia Report", "type": "main", "index": 0 }, { "node": "Dividi Email", "type": "main", "index": 0 }, { "node": "🧠 Estrai Fatti", "type": "main", "index": 0 } ] ] }, "Ottieni Token Copilot": { "main": [ [ { "node": "GPT-4.1 - Classifica Email", "type": "main", "index": 0 } ] ] }, "⏰ Ogni 3 ore": { "main": [ [ { "node": "Gmail - Leggi tutte le label", "type": "main", "index": 0 } ] ] }, "Ha azione Paperless?": { "main": [ [ { "node": "Ha PDF allegato?", "type": "main", "index": 0 } ], [ { "node": "Risolvi ID Label", "type": "main", "index": 0 } ] ] }, "È un test?": { "main": [ [ { "node": "Gmail - Fetch tutte non lette", "type": "main", "index": 0 } ], [ { "node": "Gmail - Fetch ultime 3h", "type": "main", "index": 0 } ] ] }, "Gmail - Fetch tutte non lette": { "main": [ [ { "node": "Gmail - Leggi contenuto", "type": "main", "index": 0 } ] ] }, "Gmail - Fetch ultime 3h": { "main": [ [ { "node": "Gmail - Leggi contenuto", "type": "main", "index": 0 } ] ] }, "Ha PDF allegato?": { "main": [ [ { "node": "Estrai Allegati PDF", "type": "main", "index": 0 } ], [ { "node": "Chiama Core Upload", "type": "main", "index": 0 } ] ] }, "Estrai Allegati PDF": { "main": [ [ { "node": "Chiama Core Upload", "type": "main", "index": 0 } ] ] }, "🧠 Estrai Fatti": { "main": [ [ { "node": "πŸ”€ Ha Fatti?", "type": "main", "index": 0 } ] ] }, "πŸ”€ Ha Fatti?": { "main": [ [ { "node": "πŸ’Ύ Upsert Memoria", "type": "main", "index": 0 } ], [] ] } }, "settings": { "executionOrder": "v1", "availableInMCP": false, "callerPolicy": "workflowsFromSameOwner" }, "triggerCount": 2, "versionId": "ba68ff52-7646-45ef-b999-af915df23a00", "owner": { "type": "personal", "projectId": "Hdttz401OqqtObPo", "projectName": "Martin Tahiraj ", "personalEmail": "tahiraj.martin@gmail.com" }, "parentFolderId": null, "isArchived": false }