Saltar al contenido

Automatización de Resumen de Newsletters con IA (Asuntos Públicos)

Recopila, limpia y resume newsletters de Gmail en Google Sheets. Utiliza IA (Google Gemini y Langchain) para analizar contenido y generar un briefing ejecutivo diario en HTML, enviado por email.

AIn8n 17 nodos 9 tipos conectado
Cargando workflow...

Nodos

MemoryBufferWindow EmailSend LmChatGoogleGemini Gmail GoogleSheets ScheduleTrigger Code Set StickyNote

Herramientas

Gmail Google Sheets Google Gemini Chat Model Langchain Email

Detalles

ID
9633
Nodos
17
Conex.
Tipos
9

Pertenece a:

¿Qué hace este workflow?

Este workflow transforma la gestión de información estratégica, automatizando completamente la recopilación, limpieza y resumen de newsletters recibidas en Gmail. Utilizando la potencia de la Inteligencia Artificial con Google Gemini y Langchain, el sistema analiza el contenido para generar un briefing ejecutivo diario y estructurado en formato HTML. Este informe se envía automáticamente por email a los stakeholders clave, garantizando que el equipo de asuntos públicos o cualquier rol directivo esté siempre al tanto de las novedades relevantes sin esfuerzo manual. Optimiza la toma de decisiones al proporcionar información curada y concisa, liberando horas de trabajo manual en lectura y preparación de resúmenes. Asegura la coherencia y puntualidad en la comunicación interna de inteligencia de mercado o sectorial.

¿Cómo funciona?

Este workflow usa 17 nodos conectados con 9 tipos diferentes: MemoryBufferWindow, EmailSend, LmChatGoogleGemini, Gmail, GoogleSheets y 4 más. La estructura está totalmente conectada — listo para importar.

¿Para quién es?

Diseñado para empresas de Servicios Profesionales y equipos de Marketing & Email. Nivel intermedio — necesitas familiaridad con n8n. Alto valor de negocio: automatiza una tarea recurrente con impacto directo.

¿Lo quieres en tu empresa?

Lo implementamos por ti end-to-end: integración, deploy, mantenimiento y soporte. Consultoría B2B con Genai Sapiens.

Hablemos de tu proyecto

¿Quieres aprender a hacerlo?

Sprints de 30 días con companion IA + comunidad. Aprende n8n, automatización y agentes IA desde cero o nivel avanzado.

Ver formación Momentum

Workflows similares

/gi, '')\n .replace(//gi, '')\n .replace(//gi, '')\n .replace(//g, '')\n .replace(/]*>/gi, '')\n .replace(/]*>/gi, '');\n\n// 3) Übrige HTML-Tags strippen\ns = s.replace(/<[^>]+>/g, '');\n\n// 4) HTML-Entities & Zero-Width-Zeichen normalisieren\ns = s\n .replace(/ /gi, ' ')\n .replace(/&/gi, '&')\n .replace(/"/gi, '\"')\n .replace(/'/gi, \"'\")\n .replace(/</gi, '<')\n .replace(/>/gi, '>')\n .replace(/[​-‍⁠­]/g, '')\n .replace(/[   ]/g, ' ')\n .replace(/ /g, ' ');\n\n// 5) Links stark reduzieren\ns = s.replace(/https?://[^\\s)]+/g, (url) => {\n const low = url.toLowerCase();\n // Komplett entfernen\n if (/(unsubscribe|abmelden|privacy|datenschutz|linkedin|facebook|twitter|instagram|update.*preferences|newsletter.*verwalten|impressum|kontakt|anmelden|registr|login|account)/i.test(low)) return '';\n // Kurz halten für relevante Links\n const base = url.split('?')[0];\n if (base.length > 60) return base.substring(0, 60) + '...';\n return KEEP_LINKS_BASE ? base : '';\n});\n\n// 6) Email-Adressen entfernen\ns = s.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, '[E-Mail]');\n\n// 7) SEHR AGGRESSIVE Boilerplate-Filter\nconst boilerplate = [\n 'Im Browser ansehen', 'Zum Briefing', 'Briefing im Browser öffnen', 'Browser lesen',\n 'Zurück nach oben', '^Anzeige$', '^Presseschau$', '^Nachrichten$',\n '^Die wichtigsten Themen im Überblick:?$', '^Folgen Sie .* auf LinkedIn$',\n 'Hilfe & Support', '^Zum\\\\s+Tagesspiegel Background$', 'Hier geht.*zur Anmeldung',\n 'Gesundheit & E-Health', 'Smart\\\\s*City', 'Energie\\\\s*&\\\\s*Klima',\n 'Digitalisierung\\\\s*&\\\\s*KI', 'Sustainable\\\\s*Finance', 'Verkehr\\\\s*&\\\\s*Smart\\\\s*Mobility',\n 'Agrar\\\\s*&\\\\s*Ernährung', 'Cybersecurity', '^Tipp:$',\n '^Mehr\\\\s+auf\\\\s+pkv\\\\.de$', '^Mit\\\\s+Caspar\\\\s+Schwietering$',\n '^dpa$', '^ibi$', '^AFP$', '^Reuters$', '^KNA$', '^csa$',\n 'Fragen zu redaktionellen Inhalten:', 'Fragen zu Anzeigen:', 'Fragen zum Abonnement',\n '^Sie möchten.*kompakterer Form\\\\?$', 'Hier können Sie.*aktivieren',\n 'Diese.*Newsletter.*an', 'Wurde Ihnen.*weitergeleitet', 'Jetzt.*weiterlesen',\n 'Möchten Sie ändern.*E-Mails', 'Newsletter verwalten', 'von dieser Liste',\n 'Fügen Sie.*Adressbuch', 'Sichern Sie sich', 'Lizenz kaufen',\n 'Individuelles Angebot', '^Kontakt$', '^Datenschutz$', '^Impressum$',\n '^Mediadaten$', 'Klicken Sie hier', 'update your preferences',\n 'This email was sent', 'ABONNIEREN Sie', 'Jetzt Artikel lesen',\n 'Jetzt mit H\\\\+ weiterlesen', '^Jobs$', '^Weitere Jobs finden$',\n 'Handelsblatt-Probeabo', 'Zur Angebotsauswahl', '^Podcast:',\n 'Hören statt lesen', 'Das Handelsblatt als E-Paper', '^Karikatur$',\n 'Wie zufrieden sind Sie', 'Sie haben Fragen.*Kritik', '^Bonus$',\n 'Morning Briefing als Podcast', '^Latest News$', 'Was heute noch wichtig ist',\n '^Mit H\\\\+ lesen Sie auch$', '^Geldanlage plus$', '^Kopf des Tages',\n 'Sie lesen die kostenlose Vorschau', '^Monitoring$', '^Briefing$',\n 'Eine umfangreiche Presseschau', 'Jeden Morgen um 6 Uhr',\n 'Der Tagesspiegel Background.*erscheint', 'Alle Artikel.*finden Sie',\n 'Mehr über das Monitoring', 'Monat kostenlos testen',\n 'Untersuchen und beobachten Sie', 'Erhalten Sie den vollen Zugang'\n];\n\nconst boilerRe = new RegExp(`^(${boilerplate.join('|')})\\\\s*$`, 'i');\n\n// 8) KOMPLETT Footer abschneiden (sehr aggressiv)\nconst footerMarkers = [\n 'Verlag Der Tagesspiegel GmbH', 'Geschäftsführer:', 'Chefredakteur',\n 'AG Charlottenburg', 'Diese kostenlosen Newsletter', 'ABONNIEREN Sie die Newsletter',\n 'Brussels Playbook', 'London Playbook', 'DC Decoded', 'Global Playbook',\n 'Fragen zum Datenschutz', 'background.service@tagesspiegel.de',\n 'Copyright', '© 20', 'Alle Rechte vorbehalten'\n];\n\nfor (const marker of footerMarkers) {\n const idx = s.indexOf(marker);\n if (idx > s.length * 0.5) { // nur wenn im letzten Drittel\n s = s.substring(0, idx).trim();\n break;\n }\n}\n\n// 9) Zeilen filtern\nconst lines = s.split('\n');\nconst filteredLines = [];\nlet lastLine = '';\nlet inPresseschau = false;\nlet presseschauCount = 0;\nlet anzeigenSkipLines = 0;\n\nfor (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n \n // Komplett leere Zeilen\n if (!line) {\n if (lastLine !== '') filteredLines.push('');\n lastLine = '';\n continue;\n }\n \n // Boilerplate überspringen\n if (boilerRe.test(line)) {\n lastLine = '';\n continue;\n }\n \n // Anzeigen-Block: Max 6 Zeilen überspringen, aber früher stoppen bei echtem Content\n if (/^Anzeige$/i.test(line) || /^\\(Anzeige\\)/i.test(line)) {\n anzeigenSkipLines = 6;\n continue;\n }\n \n if (anzeigenSkipLines > 0) {\n anzeigenSkipLines--;\n // Früher stoppen, wenn echte Überschrift oder längerer Content kommt\n if (line.length > 40 && /^[A-Z]/.test(line) && !/(Mehr|Jetzt|www\\.|https?:)/i.test(line)) {\n anzeigenSkipLines = 0; // Abbrechen, ist echter Content\n } else {\n continue; // Weiter überspringen\n }\n }\n \n // Presseschau MASSIV reduzieren\n if (/^Presseschau$/i.test(line)) {\n filteredLines.push('\n=== Presseschau (stark gekürzt) ===');\n inPresseschau = true;\n presseschauCount = 0;\n lastLine = line;\n continue;\n }\n \n if (inPresseschau) {\n presseschauCount++;\n // Nur erste 3 Einträge behalten\n if (presseschauCount > 6) {\n if (/^[A-Z][\\w\\s&-]{15,}$/.test(line) && line !== line.toUpperCase()) {\n inPresseschau = false;\n } else {\n continue;\n }\n }\n }\n \n // Sehr kurze Link-Zeilen entfernen\n if (line.length < 20 && /^https?:|^www\\.|\\.de$|\\.com$/i.test(line)) continue;\n \n // \"Mehr lesen\" etc.\n if (/^(Mehr lesen|Weiterlesen|Jetzt lesen|Hier lesen|Zum Artikel)$/i.test(line)) continue;\n \n // Wiederholte Zeilen vermeiden\n if (line === lastLine) continue;\n \n // Zeilen mit nur Sonderzeichen\n if (/^[\\s\\-——=_*#]+$/.test(line)) continue;\n \n // Sehr kurze Zeilen (außer Überschriften)\n if (line.length < 3 && !/^[IVX0-9]+$/i.test(line)) continue;\n \n filteredLines.push(line);\n lastLine = line;\n}\n\ns = filteredLines.join('\n');\n\n// 10) Mehrfache Leerzeilen komprimieren\ns = s\n .replace(/[ \t]+\n/g, '\n')\n .replace(/\n{4,}/g, '\n\n\n')\n .replace(/[ \t]{2,}/g, ' ')\n .trim();\n\n// 11) Excel-Formel-Schutz\nif (/^[+=]/.test(s)) s = \"'\" + s;\n\n// 12) Längencheck für Debugging\nconsole.log(`Länge nach Bereinigung: ${s.length} Zeichen`);\n\nreturn { ...$json, cleanText: s, cleanLength: s.length };"},"typeVersion":2},{"id":"63fa5ffb-dad9-486e-aadc-fc89569b0145","name":"Split in Chunks","type":"n8n-nodes-base.code","position":[640,0],"parameters":{"jsCode":"// Function: Text in mehrere Zeilen aufteilen wenn > 50.000 Zeichen\nconst MAX_LENGTH = 50000;\nconst items = [];\n\nfor (const item of $input.all()) {\n const text = item.json.cleanText || item.json.Text || '';\n const absender = item.json.Absenderadresse || '';\n const absenderName = item.json.Absendername || '';\n const betreff = item.json.Betreff || '';\n \n // Wenn Text kurz genug ist: normal durchreichen\n if (text.length <= MAX_LENGTH) {\n items.push({\n json: {\n Absenderadresse: absender,\n Absendername: absenderName,\n Betreff: betreff,\n Text: text,\n Teil: '1/1',\n Zeichenanzahl: text.length\n }\n });\n continue;\n }\n \n // Text ist zu lang: in Chunks aufteilen\n const chunks = [];\n let remaining = text;\n \n while (remaining.length > 0) {\n let chunk = remaining.substring(0, MAX_LENGTH);\n \n // Versuche bei Absatz-Ende zu schneiden (nicht mitten im Wort)\n if (remaining.length > MAX_LENGTH) {\n const lastNewline = chunk.lastIndexOf('\n\n');\n const lastPeriod = chunk.lastIndexOf('. ');\n \n // Schneide bei Absatz oder Satzende\n const cutPoint = lastNewline > MAX_LENGTH - 500 ? lastNewline : \n lastPeriod > MAX_LENGTH - 200 ? lastPeriod + 1 : \n MAX_LENGTH;\n \n chunk = remaining.substring(0, cutPoint);\n }\n \n chunks.push(chunk.trim());\n remaining = remaining.substring(chunk.length).trim();\n }\n \n // Für jeden Chunk ein Item erstellen\n chunks.forEach((chunk, index) => {\n items.push({\n json: {\n Absenderadresse: absender,\n Absendername: absenderName,\n Betreff: `${betreff} (Teil ${index + 1}/${chunks.length})`,\n Text: chunk,\n Teil: `${index + 1}/${chunks.length}`,\n Zeichenanzahl: chunk.length\n }\n });\n });\n}\n\nreturn items;"},"typeVersion":2},{"id":"086ea1bd-8075-4856-be16-0f9d83e9c7bc","name":"Set Table Fields","type":"n8n-nodes-base.set","position":[864,0],"parameters":{"options":{},"assignments":{"assignments":[{"id":"e1bb9a57-e7d5-479b-af92-22ab5a93dcd5","name":"Absenderadresse","type":"string","value":"={{ $json.Absenderadresse }}"},{"id":"06048f24-3da8-4978-bf6d-54bbfe5b3ced","name":"Absendername","type":"string","value":"={{ $json.Absendername }}"},{"id":"3077d498-ee8a-41f1-a4c9-57018ca01ec6","name":"Betreff","type":"string","value":"={{ $json.Betreff }}"},{"id":"6beb9b2a-a672-4a6b-941f-de7cb1041869","name":"Text","type":"string","value":"={{ $json.Text }}"}]}},"typeVersion":3.4},{"id":"d1676830-038e-418a-950a-8539ca9f1791","name":"Append Row","type":"n8n-nodes-base.googleSheets","position":[1088,0],"parameters":{"columns":{"value":{},"schema":[{"id":"Absenderadresse","type":"string","display":true,"removed":false,"required":false,"displayName":"Absenderadresse","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Absendername","type":"string","display":true,"removed":false,"required":false,"displayName":"Absendername","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Betreff","type":"string","display":true,"removed":false,"required":false,"displayName":"Betreff","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Text","type":"string","display":true,"removed":false,"required":false,"displayName":"Text","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"autoMapInputData","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"name","value":"={{ $('Google Spreadsheet').first().json.sheets[0].properties.title }}"},"documentId":{"__rl":true,"mode":"id","value":"={{ $('Google Spreadsheet').first().json.spreadsheetId }}"}},"typeVersion":4.7},{"id":"a9ebbba4-06a6-4137-8fce-8c94c31b8597","name":"Public Affairs Consultant","type":"@n8n/n8n-nodes-langchain.code","position":[1440,0],"parameters":{"code":{"execute":{"code":"const llm = await this.getInputConnectionData('ai_languageModel', 0)\nconst { PromptTemplate } = require('@langchain/core/prompts')\nconst { RunnableSequence } = require('@langchain/core/runnables')\nconst { JsonOutputParser } = require('@langchain/core/output_parsers')\n\nconst jsonParser = new JsonOutputParser()\n\n// ========================================\n// Alle Newsletter einsammeln\n// ========================================\nconst allNewsletters = [];\nlet totalText = '# NEWSLETTER BRIEFING\n\n';\n\nfor (const item of $input.all()) {\n const betreff = item.json.Betreff || 'Ohne Betreff';\n const absender = item.json.Absendername || item.json.Absenderadresse || 'Unbekannt';\n const text = item.json.Text || '';\n allNewsletters.push({ absender, betreff, text });\n\n totalText += `## Newsletter ${allNewsletters.length}\n`;\n totalText += `**Von:** ${absender}\n`;\n totalText += `**Betreff:** ${betreff}\n\n`;\n totalText += `${text}\n\n`;\n totalText += '---\n\n';\n}\n\nconst newsletterCount = allNewsletters.length;\nconst today = new Date().toLocaleDateString('de-DE');\n\n// ========================================\n// LANGFASSUNG (Deep Dive) - AUF DEUTSCH\n// ========================================\nconst longPrompt = PromptTemplate.fromTemplate(`\n\nDu bist ein erfahrener Policy-Analyst und strategischer Berater für Public Affairs Professionals.\n\n\n\nAnalysiere ALLE {count} Newsletter von heute ({date}) und erstelle ein umfassendes Briefing (1500-2500 Wörter auf DEUTSCH). \nSynthetisiere Informationen aus allen Quellen, identifiziere Muster und gib strategische Empfehlungen.\n\n\n\nWICHTIG: Antworte ausschließlich auf DEUTSCH. Alle Texte, Analysen und Empfehlungen müssen in deutscher Sprache verfasst sein.\n\n\n\nDer Leser benötigt:\n- Umfassende Analyse über mehrere Quellen hinweg\n- Stakeholder-Positionen und deren Implikationen\n- Strategische Risiken und Chancen\n- Wie sich verschiedene Quellen ergänzen oder widersprechen\n- Handlungsempfehlungen basierend auf dem Gesamtbild\n\n\n\n\n\n{input}\n\n\n\nGib NUR valides JSON zurück (alle Textinhalte auf DEUTSCH). WICHTIG: Verwende doppelte geschweifte Klammern für das JSON-Format:\n\n{{\n \"executiveSummary\": \"3-4 Sätze Überblick auf DEUTSCH\",\n \"sourcesAnalyzed\": {count},\n \"majorThemes\": [\n {{\n \"theme\": \"Themenname auf Deutsch\",\n \"description\": \"Beschreibung auf Deutsch\",\n \"mentionedIn\": [\"Quelle 1\", \"Quelle 2\"],\n \"strategicImportance\": \"Strategische Bedeutung auf Deutsch\"\n }}\n ],\n \"keyDevelopments\": [\n {{\n \"topic\": \"Thema auf Deutsch\",\n \"details\": \"Details auf Deutsch\",\n \"sources\": [\"Quelle 1\"],\n \"implications\": \"Implikationen auf Deutsch\"\n }}\n ],\n \"stakeholderAnalysis\": \"Analyse der wichtigsten Akteure über alle Quellen hinweg AUF DEUTSCH\",\n \"crossCuttingInsights\": \"Übergreifende Erkenntnisse aus allen Quellen AUF DEUTSCH\",\n \"strategicImplications\": \"Bedeutung für Corporate Affairs Strategie AUF DEUTSCH\",\n \"recommendedActions\": [\"Handlungsempfehlung 1 auf Deutsch\", \"Handlungsempfehlung 2 auf Deutsch\"],\n \"gapsAndQuestions\": [\"Offene Frage 1 auf Deutsch\", \"Offene Frage 2 auf Deutsch\"]\n}}\n\n\n\nWICHTIG: Die gesamte Analyse, alle Beschreibungen, Empfehlungen und Erkenntnisse müssen auf DEUTSCH verfasst sein!\n\n`);\n\n// Chain nur für Langfassung\nconst longChain = RunnableSequence.from([longPrompt, llm, jsonParser]);\n\ntry {\n const longResponse = await longChain.invoke({ \n input: totalText,\n count: newsletterCount,\n date: today\n });\n\n const timestamp = new Date().toISOString().split('T')[0];\n const filename = `PA-Briefing_${timestamp}_${newsletterCount}NL_REPORT.json`;\n\n // EIN Output, EIN Item\n return [\n {\n json: {\n type: \"deep_dive_report\",\n date: today,\n newslettersAnalyzed: newsletterCount,\n executiveSummary: longResponse.executiveSummary || '',\n majorThemes: longResponse.majorThemes || [],\n keyDevelopments: longResponse.keyDevelopments || [],\n stakeholderAnalysis: longResponse.stakeholderAnalysis || '',\n crossCuttingInsights: longResponse.crossCuttingInsights || '',\n strategicImplications: longResponse.strategicImplications || '',\n recommendedActions: longResponse.recommendedActions || [],\n gapsAndQuestions: longResponse.gapsAndQuestions || [],\n filename: filename,\n createdAt: new Date().toISOString()\n }\n }\n ];\n\n} catch (error) {\n return [\n {\n json: {\n error: true,\n message: error.message,\n newslettersReceived: newsletterCount\n }\n }\n ];\n}"}},"inputs":{"input":[{"type":"main"},{"type":"ai_languageModel","maxConnections":1},{"type":"ai_memory","maxConnections":1}]},"outputs":{"output":[{"type":"main"}]}},"typeVersion":1},{"id":"16ecc421-cb56-4e37-b544-cb061b17ed31","name":"Structure HTML-Mail","type":"n8n-nodes-base.code","position":[1952,0],"parameters":{"jsCode":"// Funktion um Markdown in HTML zu konvertieren\nfunction markdownToHtml(text) {\n if (!text) return 'N/A';\n \n return text\n // ** bold ** zu \n .replace(/\\*\\*([^*]+)\\*\\*/g, '$1')\n \n // * Listen-Items zu
  • \n .replace(/^\\s*\\*\\s+(.+)$/gm, '
  • $1
  • ')\n \n // Doppelte Zeilenumbrüche = neue Absätze\n .replace(/\n\n/g, '

    ')\n \n // Einzelne Zeilenumbrüche =
    \n .replace(/\n/g, '
    ')\n \n // Wrap Listen in

      \n .replace(/(
    • .*?
    • )/gs, '
        $1
      ')\n \n // Wrap Text in Paragraphen (nur wenn noch nicht wrapped)\n .replace(/^(?!<[pu])/gm, '

      ')\n .replace(/(?)$/gm, '

      ');\n}\n\nconst json = $input.item.json;\n\n// HTML Template mit Markdown-Konvertierung\nconst html = `\n\n\n \n\n\n

      Newsletter Briefing

      \n \n
      \n 📊 Analysierte Newsletter: ${json.newslettersAnalyzed}
      \n 📅 Datum: ${json.date}\n
      \n\n

      Executive Summary

      \n
      ${markdownToHtml(json.executiveSummary)}
      \n\n

      Hauptthemen

      \n ${json.majorThemes ? json.majorThemes.map(t => `\n
      \n

      ${t.theme}

      \n ${markdownToHtml(t.description)}\n

      Erwähnt in: ${t.mentionedIn ? t.mentionedIn.join(', ') : 'N/A'}

      \n

      Strategische Bedeutung: ${markdownToHtml(t.strategicImportance)}

      \n
      \n `).join('') : '

      Keine Themen verfügbar

      '}\n\n

      Stakeholder-Analyse

      \n
      ${markdownToHtml(json.stakeholderAnalysis)}
      \n\n

      Übergreifende Erkenntnisse

      \n
      ${markdownToHtml(json.crossCuttingInsights)}
      \n\n

      Strategische Implikationen

      \n
      ${markdownToHtml(json.strategicImplications)}
      \n\n

      Empfohlene Aktionen

      \n ${json.recommendedActions ? json.recommendedActions.map((a, i) => `\n
      ${i+1}. ${a}
      \n `).join('') : '

      Keine Aktionen

      '}\n\n

      Offene Fragen

      \n ${json.gapsAndQuestions ? json.gapsAndQuestions.map((q, i) => `\n
      ${i+1}. ${q}
      \n `).join('') : '

      Keine offenen Fragen

      '}\n\n
      \n Automatisch generiert durch KI-Analyse | ${json.newslettersAnalyzed} Quellen\n
      \n\n`;\n\nreturn [{ json: { ...json, html } }];"},"typeVersion":2},{"id":"82ec1fd7-354c-4115-b27e-0efe0c108b81","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-880,-176],"parameters":{"width":400,"height":320,"content":"## Overview\n\n**Step 1:** Collect: Fetch ~10 newsletters from Gmail and strip HTML noise.\n**Step 2:** Organize: Chunk long texts (token-safe), log chunks + metadata to Google Sheets.\n**Step 3:** Summarize & Send: An LLM creates a concise daily digest (key topics, implications, actions), builds an HTML email, and sends it to stakeholders.\n\n**Note:** This template is not limited to Public Affairs. Swap the prompt and filters to use it for Legal, ESG, Finance, Marketing, Competitive Intel, etc."},"typeVersion":1},{"id":"68c78878-0678-4500-85cf-40e842090ff9","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-304,-240],"parameters":{"width":432,"height":464,"content":"## Group A – Timing & Destination\n\n**When & where**\n• Runs daily at the set time.\n• Creates/updates a Google Sheet to store raw text + metadata.\n\nCustomize: Interval/time; sheet name/tab."},"typeVersion":1},{"id":"aa154741-1d13-4eba-ab88-0df4a5bc8ade","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[160,-304],"parameters":{"width":1088,"height":528,"content":"## Inbox, Pre-Clean & Chunking \n\n**Collect & sanitize**\n• Pulls the 10 target newsletters via Gmail query.\n• Removes HTML clutter, trackers, inline styles → clean plain text.\n\n**Customize:** Gmail query (e.g., label:PA-News newer_than:1d), sender/subject filters.\n\n**Token-safe structuring**\n• Splits long bodies into manageable chunks.\n• Maps fields (date, source, subject, chunk id, text).\n\n**Customize:** Chunk size, field names, destination sheet/tab."},"typeVersion":1},{"id":"4a01fa46-b13f-4fe8-be15-2220af449f28","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1312,-304],"parameters":{"width":528,"height":688,"content":"## LLM Policy Digest\n\n**Create the daily brief**\n• Merges chunks into one digest with: Top topics, EU/DE relevance, risks/opportunities, action items.\n• Memory saves content when you want to analyze the newsletters over a longer period of time.\n\nCustomize: System prompt (tone, depth, output format), temperature/tokens, memory scope.\n\nReuse beyond PA: Change the prompt to Legal, ESG, Finance, Competitive Intel, Marketing, etc."},"typeVersion":1},{"id":"739d7e59-6b61-4436-a46f-2f88d2530a91","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1888,-208],"parameters":{"width":496,"height":416,"content":"Build & Send Email \n\n**Deliver the digest**\n• Generates a clean HTML email (headline, TL;DR, bullets, sources).\n• Sends to the PA Director/team (add CC/BCC as needed).\nCustomize: Recipients, subject , branding.)"},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"connections":{"Gmail":{"main":[[{"node":"Parse HTML-Code","type":"main","index":0}]]},"Memory3":{"ai_memory":[[{"node":"Public Affairs Consultant","type":"ai_memory","index":0}]]},"Append Row":{"main":[[{"node":"Public Affairs Consultant","type":"main","index":0}]]},"Parse HTML-Code":{"main":[[{"node":"Split in Chunks","type":"main","index":0}]]},"Split in Chunks":{"main":[[{"node":"Set Table Fields","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Google Spreadsheet","type":"main","index":0}]]},"Set Table Fields":{"main":[[{"node":"Append Row","type":"main","index":0}]]},"Google Spreadsheet":{"main":[[{"node":"Gmail","type":"main","index":0}]]},"Structure HTML-Mail":{"main":[[{"node":"Send email","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Public Affairs Consultant","type":"ai_languageModel","index":0}]]},"Public Affairs Consultant":{"main":[[{"node":"Structure HTML-Mail","type":"main","index":0}]]}}}