{"workflow":{"id":13466,"name":"Run AI-scored cold email outreach and follow-ups with Ollama and Gmail","views":219,"recentViews":1,"totalViews":219,"createdAt":"2026-02-17T11:59:54.805Z","description":"## **Who is this for?**\n\nThis workflow is built for founders, sales teams, solopreneurs, and agencies who want to automate outbound sales without expensive tools. Perfect for anyone doing cold email outreach who wants AI-powered personalization at scale.\n\n## **What it does**\n\nThe workflow runs three automated flows:\n\n**Flow 1 — New Lead Processing (8 AM weekdays):**\n- Reads new leads from Google Sheets\n- Scrapes the lead's website to build a research dossier\n- AI scores each lead (0–100) on company fit, role fit, timing signals, and engagement potential\n- For leads scoring 40+, AI generates 3 personalized cold emails with different angles\n- Sends Email 1 immediately and saves all 3 emails to the sheet\n- Low-fit leads are marked as skipped\n\n**Flow 2 — Follow-up Engine (every 2 hours weekdays):**\n- Checks for leads that need follow-ups\n- Sends Email 2 after 3 days, Email 3 after 7 days\n- Automatically marks sequence as complete after Email 3\n- Skips leads that have already replied\n\n**Flow 3 — Reply Detection (every 2 hours weekdays):**\n- Searches Gmail for replies from active leads\n- Filters out your own sent emails to avoid false positives\n- When a reply is found, marks the lead as \"replied\" and stops the sequence\n- Sends a Telegram alert with the reply preview\n\n## **Setup steps**\n\n1. **Google Sheets** — Create a spreadsheet with columns: Lead Name, Email, Company, Website, Role/Title, Status, Reply Date, Reply Subject, Reply Snippet, and email tracking columns (see sticky notes in the workflow for full list)\n2. **Gmail OAuth2** — Connect your Gmail account for sending emails and searching replies\n3. **Ollama** — Install locally and pull your preferred model (e.g., `ollama pull mistral`). You can also swap for OpenAI or Anthropic\n4. **Telegram Bot** — Create via @BotFather, get your bot token and chat ID\n5. **AI Lead Scorer prompt** — Edit the system prompt with your product, ICP, and scoring criteria\n6. **AI Email Writer prompt** — Edit with your name, company, value prop, and one specific result\n7. **Sender name** — Update the sender name in the Extract Emails code node (line 12) and Find Follow-ups code node (line 9)\n8. **Gmail address** — Set your sending Gmail address in the Filter Active Leads code node (line 10) and Check Reply Results code node (line 10)\n9. **Test** — Add a test lead with status \"new\", run the research flow manually, verify emails generate correctly, then enable all schedules\n\n## **Requirements**\n- Self-hosted n8n (uses Ollama nodes)\n- Ollama running locally with at least one model installed\n- Google Sheets OAuth2 credentials\n- Gmail OAuth2 credentials\n- Telegram Bot credentials\n\n## **How to customize**\n\n- Adjust the **scoring threshold** (default 40) in the Extract Score node to be more or less selective\n- Change **follow-up timing** (default 3 and 7 days) in the Find Follow-ups code node\n- Modify **cron schedules** on any trigger to match your timezone and preferences\n- Swap **Ollama for OpenAI or Anthropic** by replacing the LLM nodes\n- Add a **LinkedIn enrichment step** before the dossier builder for richer research\n- Customize email **tone and sign-off** in the AI Email Writer system prompt","workflow":{"id":"SkOA5njFb0ZAvaSy","meta":{"instanceId":"8f8ee4eb853c20789e317beb113798e3d078c0c7ef754b4b9fad98c2eee7e79d"},"name":"AI SDR — Fully Automated Cold Outreach with Scoring and Follow-ups","tags":[],"nodes":[{"id":"ff288d70-ed51-4639-a4fc-cd9f84c57e73","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[0,0],"parameters":{"width":620,"height":860,"content":"## AI SDR — Fully Automated Cold Outreach with Scoring and Follow-ups\nAutomate your entire cold email pipeline: lead research, AI scoring, personalized email generation, sending, follow-ups, and reply detection — all driven from a Google Sheet.\n\n### How it works\n1. **New Lead Processing (8 AM weekdays):** Reads new leads from Google Sheets, scrapes their website, builds a research dossier, scores them with AI, and generates 3 personalized emails.\n2. **Email 1 sent immediately** for leads scoring 40+. Low-fit leads are marked as skipped.\n3. **Follow-up engine (every 2hrs weekdays):** Sends Email 2 after 3 days, Email 3 after 7 days.\n4. **Reply detection (every 2hrs weekdays):** Searches Gmail for replies from active leads. If found, marks the lead as \"replied\" and stops the sequence.\n5. **Telegram notifications** sent at every step — emails sent, leads skipped, and replies detected.\n\n### Setup steps\n1. Connect your **Google Sheets** credential and point to your lead sheet (columns: Lead Name, Email, Company, Website, Role/Title, Status, Reply Date, Reply Subject, Reply Snippet).\n2. Connect your **Gmail** credential (OAuth2).\n3. Connect your **Telegram** credential and set `YOUR_TELEGRAM_CHAT_ID` in each Telegram node.\n4. Connect your **Ollama** credential (or swap for OpenAI/Anthropic).\n5. Edit the **AI Lead Scorer** system prompt with your product, ICP, and scoring criteria.\n6. Edit the **AI Email Writer** system prompt with your name, company, and value prop.\n7. Set your sender name in the **Extract Emails** code node (line 12) and **Find Follow-ups** code node (line 9).\n8. Set your Gmail address in the **Filter Active Leads** code node (line 10) and **Check Reply Results** code node (line 10).\n\n### Customization\n- Adjust the scoring threshold (default 40) in the **Extract Score** node.\n- Change follow-up timing (default 3 and 7 days) in the **Find Follow-ups** node.\n- Modify cron schedules on any trigger to match your timezone and preferences."},"typeVersion":1},{"id":"e6bd6e84-b8d3-4233-a3ba-a9f1e84abae2","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[1104,640],"parameters":{"color":6,"width":2260,"height":380,"content":"## 🔬 Research, Score & Send\nScrapes lead websites, builds research dossiers, scores with AI, generates 3 personalized emails, and sends Email 1 immediately."},"typeVersion":1},{"id":"90cd7117-dd95-4f9a-b230-d6f9ddef14c8","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[912,1104],"parameters":{"color":6,"width":1260,"height":420,"content":"## 📧 Follow-up Engine\nSends Email 2 after 3 days and Email 3 after 7 days. Skips leads that have already replied."},"typeVersion":1},{"id":"3be24aab-7a78-45c3-b88f-c602bcbefa28","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[912,1584],"parameters":{"color":6,"width":1304,"height":420,"content":"## 📬 Reply Detection\nSearches Gmail for replies from active leads. Marks them as \"replied\" and stops the email sequence automatically."},"typeVersion":1},{"id":"0ec61a66-98cf-4a44-84d9-37b22611b70e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[2608,1904],"parameters":{"color":3,"width":460,"content":"## ⚠️ Set your Gmail address\nEdit line 10 in both **Filter Active Leads** and **Check Reply Results** code nodes — replace `your-email@gmail.com` with your actual sending Gmail address. This prevents your own outbound emails from being detected as replies."},"typeVersion":1},{"id":"b43da6bf-e5a3-480e-953d-54d135e68bee","name":"⏰ 8 AM — New Leads","type":"n8n-nodes-base.scheduleTrigger","position":[928,752],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 8 * * 1-5"}]}},"typeVersion":1.2},{"id":"00d418c1-2115-466b-9e5e-190b83333889","name":"📋 Read Sheet (New)","type":"n8n-nodes-base.googleSheets","position":[1152,752],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"53f04d54-e0be-4437-8e4b-37bc17257e32","name":"🆕 Filter New","type":"n8n-nodes-base.code","position":[1376,752],"parameters":{"jsCode":"const allRows = $input.all();\nconst newLeads = [];\n\nfor (let i = 0; i < allRows.length; i++) {\n  const r = allRows[i].json;\n  const status = (r.Status || r.status || '').toLowerCase().trim();\n  const name = r['Lead Name'] || r.leadName || '';\n  const email = r.Email || r.email || '';\n  const website = r.Website || r.website || '';\n\n  if (status === 'new' && name && email) {\n    newLeads.push({\n      json: {\n        leadName: name,\n        company: r.Company || r.company || '',\n        website: website,\n        role: r['Role/Title'] || r.role || r.title || '',\n        email: email,\n        linkedinUrl: r['LinkedIn URL'] || r.linkedinUrl || '',\n        rowNumber: i + 2\n      }\n    });\n  }\n}\n\nif (newLeads.length === 0) {\n  return [{ json: { hasNewLeads: false } }];\n}\n\nreturn newLeads;"},"typeVersion":2},{"id":"6d454456-c5c1-4060-8006-c1ec1daeb7a5","name":"🆕 Has Leads?","type":"n8n-nodes-base.if","position":[1600,752],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"has-lead","operator":{"type":"string","operation":"notEmpty"},"leftValue":"={{ $json.leadName }}","rightValue":""}]}},"typeVersion":2.2},{"id":"77fc3456-e21c-4b0e-9434-d7a6a1e500cf","name":"🌐 Scrape Website","type":"n8n-nodes-base.code","position":[1824,656],"parameters":{"jsCode":"const lead = $json;\nlet research = { companyInfo: '', scrapedSuccessfully: false };\n\nif (!lead.website) {\n  research.companyInfo = `${lead.company} — no website provided. Role: ${lead.role}.`;\n  return { json: { ...lead, research } };\n}\n\ntry {\n  let url = lead.website;\n  if (!url.startsWith('http')) url = 'https://' + url;\n\n  const response = await this.helpers.httpRequest({\n    method: 'GET',\n    url: url,\n    timeout: 15000,\n    headers: { 'User-Agent': 'Mozilla/5.0 (compatible; research-bot)' },\n    returnFullResponse: true,\n    ignoreHttpStatusErrors: true\n  });\n\n  if (response && response.body) {\n    let html = typeof response.body === 'string' ? response.body : JSON.stringify(response.body);\n\n    const titleMatch = html.match(/<title[^>]*>(.*?)<\\/title>/i);\n    const title = titleMatch ? titleMatch[1].trim() : '';\n\n    const metaMatch = html.match(/<meta[^>]*name=[\"']description[\"'][^>]*content=[\"']([^\"']*)[\"']/i);\n    const metaDesc = metaMatch ? metaMatch[1].trim() : '';\n\n    html = html.replace(/<script[\\s\\S]*?<\\/script>/gi, ' ');\n    html = html.replace(/<style[\\s\\S]*?<\\/style>/gi, ' ');\n    html = html.replace(/<nav[\\s\\S]*?<\\/nav>/gi, ' ');\n    html = html.replace(/<footer[\\s\\S]*?<\\/footer>/gi, ' ');\n    html = html.replace(/<[^>]+>/g, ' ');\n    html = html.replace(/&nbsp;|&amp;|&lt;|&gt;/g, ' ');\n    html = html.replace(/\\s+/g, ' ').trim();\n\n    research.companyInfo = `Title: ${title}\\nDescription: ${metaDesc}\\nContent: ${html.substring(0, 1500)}`;\n    research.scrapedSuccessfully = true;\n  }\n} catch (e) {\n  research.companyInfo = `Could not scrape ${lead.website}. Company: ${lead.company}, Role: ${lead.role}.`;\n}\n\nreturn { json: { ...lead, research } };"},"typeVersion":2},{"id":"a407e7ad-a48a-49f2-8c4c-b867a9dc2b51","name":"📄 Build Dossier","type":"n8n-nodes-base.code","position":[2048,656],"parameters":{"jsCode":"const lead = $json;\nconst r = lead.research || {};\n\nconst dossier = `=== LEAD DOSSIER ===\nPerson: ${lead.leadName}\nRole: ${lead.role}\nCompany: ${lead.company}\nWebsite: ${lead.website || 'N/A'}\nEmail: ${lead.email}\n\n--- Company Research ---\n${r.companyInfo || 'No info available.'}\n\nScraped: ${r.scrapedSuccessfully ? 'Yes' : 'No'}`;\n\nreturn { json: { ...lead, dossier } };"},"typeVersion":2},{"id":"975ad2ef-3697-451e-b7cc-4b84795a5ae4","name":"📊 AI Lead Scorer","type":"@n8n/n8n-nodes-langchain.agent","position":[2272,656],"parameters":{"text":"=Score this lead for sales outreach:\n\n{{ $json.dossier }}\n\nScore 0-100.","options":{"systemMessage":"You are a sales intelligence analyst.\n\n=== YOUR PRODUCT (EDIT THIS) ===\nProduct: [YOUR PRODUCT NAME]\nWhat it does: [WHAT IT DOES]\nIdeal customer: [YOUR ICP]\nProblems solved: [KEY PROBLEMS]\n\n=== SCORING ===\n1. Company-Solution Fit (0-30): Do they have our problem?\n2. Role Fit (0-25): Can they buy? (C-level=high, IC=low)\n3. Timing Signals (0-25): Hiring? Funded? Growing?\n4. Engagement Potential (0-20): Will they respond?\n\nRAW JSON ONLY. No markdown fences.\n{\"totalScore\":0,\"companySolutionFit\":{\"score\":0,\"reason\":\"\"},\"roleFit\":{\"score\":0,\"reason\":\"\"},\"timingSignals\":{\"score\":0,\"reason\":\"\"},\"engagementPotential\":{\"score\":0,\"reason\":\"\"},\"overallAssessment\":\"\",\"recommendation\":\"pursue\",\"keyInsight\":\"\"}"},"promptType":"define","hasOutputParser":true},"typeVersion":2.1},{"id":"7454887b-5a92-4d21-b927-f8124a31eb27","name":"🎯 Extract Score","type":"n8n-nodes-base.code","position":[2624,656],"parameters":{"jsCode":"const lead = $('📄 Build Dossier').item.json;\nconst raw = $json;\nlet score = {};\n\nfunction tryParse(str) {\n  if (typeof str !== 'string') return null;\n  str = str.replace(/```json\\s*/gi, '').replace(/```\\s*/g, '').trim();\n  try { return JSON.parse(str); } catch(e) {\n    const m = str.match(/\\{[\\s\\S]*\"totalScore\"[\\s\\S]*\\}/);\n    if (m) try { return JSON.parse(m[0]); } catch(e2) {}\n    return null;\n  }\n}\n\nfunction dig(obj, d) {\n  if (d > 5 || !obj || typeof obj !== 'object') return null;\n  if (obj.totalScore !== undefined) return obj;\n  for (const k of ['output','text','message','content','response','result','data','kwargs','lc_kwargs']) {\n    if (obj[k]) {\n      if (typeof obj[k] === 'string') { const r = tryParse(obj[k]); if (r) return r; }\n      else { const r = dig(obj[k], d+1); if (r) return r; }\n    }\n  }\n  for (const k of Object.keys(obj)) {\n    if (typeof obj[k] === 'string' && obj[k].includes('totalScore')) {\n      const r = tryParse(obj[k]); if (r) return r;\n    } else if (typeof obj[k] === 'object' && obj[k]) {\n      const r = dig(obj[k], d+1); if (r) return r;\n    }\n  }\n  return null;\n}\n\ntry {\n  if (raw && raw.totalScore !== undefined) score = raw;\n  else { const f = dig(raw, 0); if (f) score = f; }\n  if (score.totalScore === undefined) {\n    const p = tryParse(JSON.stringify(raw));\n    if (p) score = p;\n  }\n} catch(e) {}\n\nif (score.totalScore === undefined) {\n  score = { totalScore: 50, recommendation: 'pursue', overallAssessment: 'AI parse failed — default score.', keyInsight: 'Review manually' };\n}\n\nreturn { json: {\n  ...lead,\n  score: score.totalScore,\n  recommendation: score.recommendation || (score.totalScore >= 40 ? 'pursue' : 'skip'),\n  keyInsight: score.keyInsight || '',\n  overallAssessment: score.overallAssessment || '',\n  shouldPursue: score.totalScore >= 40\n}};"},"typeVersion":2},{"id":"268c6d25-e5fb-4157-bb26-6a13c235a14a","name":"📊 Pursue?","type":"n8n-nodes-base.if","position":[2848,656],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"pursue","operator":{"type":"boolean","operation":"true"},"leftValue":"={{ $json.shouldPursue }}","rightValue":true}]}},"typeVersion":2.2},{"id":"e84960a8-3d0b-484d-a436-3d37174a8c5e","name":"✍️ AI Email Writer","type":"@n8n/n8n-nodes-langchain.agent","position":[3072,400],"parameters":{"text":"=Write 3 cold outreach emails for:\n\n{{ $json.dossier }}\n\nScore: {{ $json.score }}/100\nKey Insight: {{ $json.keyInsight }}\nAssessment: {{ $json.overallAssessment }}","options":{"systemMessage":"You are writing cold outreach emails.\n\n=== SENDER INFO (EDIT THIS) ===\n[YOUR NAME]: Your full name\n[YOUR COMPANY]: Your company name\n[WHAT YOU SELL]: One-line description of your product\n[#1 BENEFIT]: The main benefit your customers get\n[ONE SPECIFIC RESULT]: A concrete result you've achieved for a customer\n\n=== STRICT FORMATTING RULES ===\n\nEVERY email must follow this EXACT structure:\n\nLine 1: Greeting (Hi [FirstName],)\nLine 2: (blank line)\nLines 3-8: Body (4-6 short sentences)\nLine N-1: (blank line)\nLine N: Sign-off (Best, [YOUR NAME])\n\nFORMATTING:\n- Use real line breaks between paragraphs\n- NO markdown (no **, no ##, no bullets)\n- NO \"Subject:\" in the body\n- Keep sentences SHORT (under 20 words each)\n- One idea per paragraph\n- Max 6 sentences in body\n- Sign off with: Best, [YOUR NAME]\n\nCONTENT RULES:\n- Reference something SPECIFIC from their company research\n- Mention their role naturally\n- Email 1: Lead with THEIR world, not yours\n- Email 2: Share a different angle or result (never say \"following up\")\n- Email 3: Be human, make it easy to say no\n- Sound like a PERSON, not a salesperson\n- NO buzzwords (leverage, synergy, revolutionary, game-changing)\n- NO \"I hope this email finds you well\"\n- NO \"I came across your company\"\n\n=== SUBJECT LINE RULES ===\n- 4-7 words only\n- Lowercase (except first word and proper nouns)\n- No clickbait, no ALL CAPS\n- Create curiosity, not hype\n\n=== OUTPUT FORMAT ===\nRAW JSON ONLY. No markdown fences. No explanation.\n\n{\"email1\":{\"subject\":\"subject here\",\"body\":\"Hi FirstName,\\n\\nFirst paragraph.\\n\\nSecond paragraph.\\n\\nCTA paragraph.\\n\\nBest,\\n[YOUR NAME]\"},\"email2\":{\"subject\":\"different subject\",\"body\":\"Hi FirstName,\\n\\nDifferent angle.\\n\\nProof or insight.\\n\\nSoft CTA.\\n\\nBest,\\n[YOUR NAME]\"},\"email3\":{\"subject\":\"last note subject\",\"body\":\"Hi FirstName,\\n\\nAcknowledge outreach.\\n\\nGenuine value.\\n\\nEasy to say no.\\n\\nCheers,\\n[YOUR NAME]\"},\"personalizationUsed\":[\"specific thing 1\",\"specific thing 2\"]}"},"promptType":"define","hasOutputParser":true},"typeVersion":2.1},{"id":"b51ecaf0-3369-41ed-b2b5-d1a8fbddf1cf","name":"📝 Extract Emails","type":"n8n-nodes-base.code","position":[3424,512],"parameters":{"jsCode":"const lead = $('📊 Pursue?').item.json;\nconst raw = $json;\nlet emails = {};\n\n// ⚠️ CHANGE THIS to your name\nconst senderName = 'YOUR_NAME';\nconst firstName = lead.leadName.split(' ')[0];\n\nfunction tryParse(str) {\n  if (typeof str !== 'string') return null;\n  str = str.replace(/```json\\s*/gi, '').replace(/```\\s*/g, '').trim();\n  try { return JSON.parse(str); } catch(e) {\n    const m = str.match(/\\{[\\s\\S]*\"email1\"[\\s\\S]*\\}/);\n    if (m) try { return JSON.parse(m[0]); } catch(e2) {}\n    return null;\n  }\n}\n\nfunction dig(obj, d) {\n  if (d > 5 || !obj || typeof obj !== 'object') return null;\n  if (obj.email1 && typeof obj.email1 === 'object') return obj;\n  for (const k of ['output','text','message','content','response','result','data','kwargs','lc_kwargs']) {\n    if (obj[k]) {\n      if (typeof obj[k] === 'string') { const r = tryParse(obj[k]); if (r && r.email1) return r; }\n      else { const r = dig(obj[k], d+1); if (r) return r; }\n    }\n  }\n  for (const k of Object.keys(obj)) {\n    if (typeof obj[k] === 'string' && obj[k].includes('email1')) { const r = tryParse(obj[k]); if (r && r.email1) return r; }\n    else if (typeof obj[k] === 'object' && obj[k]) { const r = dig(obj[k], d+1); if (r) return r; }\n  }\n  return null;\n}\n\ntry {\n  if (raw && raw.email1) emails = raw;\n  else { const f = dig(raw, 0); if (f) emails = f; }\n  if (!emails.email1) { const p = tryParse(JSON.stringify(raw)); if (p && p.email1) emails = p; }\n} catch(e) {}\n\nif (!emails.email1) {\n  emails = {\n    email1: { subject: `Quick question about ${lead.company}`, body: `Hi ${firstName},\\n\\nI noticed ${lead.company} and wanted to reach out.\\n\\nWould love to share something relevant to your work as ${lead.role}.\\n\\nWorth a quick chat?\\n\\nBest,\\n${senderName}` },\n    email2: { subject: `Thought of ${lead.company}`, body: `Hi ${firstName},\\n\\nI had another thought about how we might help ${lead.company}.\\n\\nWe recently helped a similar company solve a challenge you might relate to.\\n\\nWould it make sense to share the details?\\n\\nBest,\\n${senderName}` },\n    email3: { subject: `Last note from me`, body: `Hi ${firstName},\\n\\nI know you're busy, so I'll keep this brief.\\n\\nIf the timing isn't right, totally understand.\\n\\nWishing you and ${lead.company} all the best.\\n\\nCheers,\\n${senderName}` },\n    personalizationUsed: ['company name only — AI parse failed']\n  };\n}\n\nfunction formatEmailBody(rawBody) {\n  if (!rawBody) return '';\n  let body = rawBody;\n  body = body.replace(/\\\\n/g, '\\n');\n  body = body.replace(/\\\\\\\\n/g, '\\n');\n  body = body.replace(/^Subject:.*?\\n\\n?/i, '');\n  body = body.replace(/^Subject:.*?\\n/i, '');\n  body = body.replace(/\\*\\*/g, '');\n  body = body.replace(/^#+\\s/gm, '');\n  body = body.replace(/\\[YOUR NAME\\]/gi, senderName);\n  body = body.replace(/\\[Your Name\\]/g, senderName);\n  body = body.replace(/YourName/g, senderName);\n  body = body.replace(/\\n\\n?(Best|Cheers|Thanks|Thank you|Regards|Kind regards|Warm regards|Sincerely|Talk soon|All the best),?\\s*\\n\\s*[A-Z][a-zA-Z]*(\\s+[A-Z][a-zA-Z]*)?\\s*(\\n\\n?(Best|Cheers|Thanks|Thank you|Regards|Kind regards|Warm regards|Sincerely|Talk soon|All the best),?\\s*\\n\\s*(\\[YOUR NAME\\]|YourName|[A-Z][a-zA-Z]*(\\s+[A-Z][a-zA-Z]*)?))?$/i, '');\n  body = body.replace(/\\n\\n?(Best|Cheers|Thanks|Regards|Sincerely|Talk soon),?\\s*$/i, '');\n  body = body.trimEnd();\n  if (!/^(Hi|Hey|Hello|Dear|Good)\\s/i.test(body.trim())) {\n    body = `Hi ${firstName},\\n\\n${body}`;\n  }\n  body = body + `\\n\\nBest,\\n${senderName}`;\n  body = body.replace(/\\n{4,}/g, '\\n\\n\\n').trim();\n  return body;\n}\n\nfunction formatSubject(rawSubject, emailNumber) {\n  if (!rawSubject) return `Following up — ${lead.company}`;\n  let subject = rawSubject;\n  subject = subject.replace(/^[\"']|[\"']$/g, '');\n  subject = subject.replace(/^Subject:\\s*/i, '');\n  subject = subject.replace(/\\[YOUR NAME\\]/gi, senderName);\n  if (emailNumber > 1 && !/^Re:/i.test(subject)) subject = 'Re: ' + subject;\n  subject = subject.replace(/^(Re:\\s*)+/i, 'Re: ');\n  return subject.trim();\n}\n\nfunction toHTML(plainText) {\n  let html = plainText.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\\n\\n/g, '</p><p>').replace(/\\n/g, '<br>');\n  return '<div style=\"font-family: Arial, sans-serif; font-size: 14px; color: #333; line-height: 1.6;\"><p>' + html + '</p></div>';\n}\n\nconst email1Subject = formatSubject(emails.email1.subject, 1);\nconst email1Body = formatEmailBody(emails.email1.body);\nconst email2Subject = formatSubject(emails.email2.subject || emails.email1.subject, 2);\nconst email2Body = formatEmailBody(emails.email2.body);\nconst email3Subject = formatSubject(emails.email3.subject || emails.email1.subject, 3);\nconst email3Body = formatEmailBody(emails.email3.body);\n\nreturn { json: {\n  leadName: lead.leadName, company: lead.company, email: lead.email,\n  role: lead.role, website: lead.website, score: lead.score,\n  keyInsight: lead.keyInsight, overallAssessment: lead.overallAssessment,\n  rowNumber: lead.rowNumber,\n  email1Subject, email1Body, email1HTML: toHTML(email1Body),\n  email2Subject, email2Body, email2HTML: toHTML(email2Body),\n  email3Subject, email3Body, email3HTML: toHTML(email3Body),\n  email1Full: 'Subject: ' + email1Subject + '\\n\\n' + email1Body,\n  email2Full: 'Subject: ' + email2Subject + '\\n\\n' + email2Body,\n  email3Full: 'Subject: ' + email3Subject + '\\n\\n' + email3Body,\n  personalizationUsed: Array.isArray(emails.personalizationUsed) ? emails.personalizationUsed.join(', ') : ''\n}};"},"typeVersion":2},{"id":"6f9bc1bd-d6da-4415-9326-130018f64386","name":"📧 Send Email 1","type":"n8n-nodes-base.gmail","position":[3648,512],"webhookId":"d17504f1-9895-4ada-a34b-e225d5ec65b2","parameters":{"sendTo":"={{ $json.email }}","message":"={{ $json.email1HTML }}","options":{"appendAttribution":false},"subject":"={{ $json.email1Subject }}"},"typeVersion":2.1},{"id":"7be872d9-8aef-43fe-b79c-aa848628fef9","name":"💾 Save + Mark Sent","type":"n8n-nodes-base.googleSheets","position":[3872,608],"parameters":{"columns":{"value":{"Status":"email_1_sent","Lead Name":"={{ $('📝 Extract Emails').item.json.leadName }}","email 3 sub":"={{ $('📝 Extract Emails').item.json.email3Subject }}","email 1 body":"={{ $('📝 Extract Emails').item.json.email1Body }}","email 2 body":"={{ $('📝 Extract Emails').item.json.email2Body }}","email 3 body":"={{ $('📝 Extract Emails').item.json.email3Body }}","email 1subject":"={{ $('📝 Extract Emails').item.json.email1Subject }}","email 2 subject":"={{ $('📝 Extract Emails').item.json.email2Subject }}","email 1 body html":"={{ $('📝 Extract Emails').item.json.email1HTML }}","email 1 sent date":"={{ new Date().toISOString() }}","email 2 body html":"={{ $('📝 Extract Emails').item.json.email2HTML }}","email 3 body html":"={{ $('📝 Extract Emails').item.json.email3HTML }}"},"schema":[{"id":"Lead Name","type":"string","display":true,"removed":false,"required":false,"displayName":"Lead Name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Status","type":"string","display":true,"required":false,"displayName":"Status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 1subject","type":"string","display":true,"required":false,"displayName":"email 1subject","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 1 body","type":"string","display":true,"required":false,"displayName":"email 1 body","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 1 sent date","type":"string","display":true,"required":false,"displayName":"email 1 sent date","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 1 body html","type":"string","display":true,"required":false,"displayName":"email 1 body html","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 subject","type":"string","display":true,"required":false,"displayName":"email 2 subject","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 body","type":"string","display":true,"required":false,"displayName":"email 2 body","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 body html","type":"string","display":true,"required":false,"displayName":"email 2 body html","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 sub","type":"string","display":true,"required":false,"displayName":"email 3 sub","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 body","type":"string","display":true,"required":false,"displayName":"email 3 body","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 body html","type":"string","display":true,"required":false,"displayName":"email 3 body html","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Lead Name"],"attemptToConvertTypes":false,"convertFieldsToString":true},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"1441a932-a034-4196-b322-ac6272e7af10","name":"📲 Email 1 Sent ✅","type":"n8n-nodes-base.telegram","position":[3872,416],"webhookId":"79f617ca-c43b-47dd-a587-1d6eec054a48","parameters":{"text":"=🚀 *Email 1 Sent — Auto-SDR*\n\n👤 {{ $('📝 Extract Emails').item.json.leadName }}\n🏢 {{ $('📝 Extract Emails').item.json.company }} ({{ $('📝 Extract Emails').item.json.role }})\n📊 Score: {{ $('📝 Extract Emails').item.json.score }}/100\n📧 To: {{ $('📝 Extract Emails').item.json.email }}\n📝 Subject: {{ $('📝 Extract Emails').item.json.email1Subject }}\n\n💡 {{ $('📝 Extract Emails').item.json.keyInsight }}\n\n_Email 2 in 3 days. Email 3 in 7 days._\n⏰ {{ new Date().toLocaleString() }}","chatId":"YOUR_TELEGRAM_CHAT_ID","additionalFields":{"parse_mode":"Markdown"}},"typeVersion":1.2},{"id":"3b92637a-f2c2-432c-b957-03ecf5526c8a","name":"⏭️ Mark Skipped","type":"n8n-nodes-base.googleSheets","position":[3136,800],"parameters":{"columns":{"value":{"Status":"low_fit_skipped","Lead Name":"={{ $json.leadName }}"},"schema":[{"id":"Lead Name","type":"string","display":true,"removed":false,"required":false,"displayName":"Lead Name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Status","type":"string","display":true,"required":false,"displayName":"Status","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Lead Name"],"attemptToConvertTypes":false,"convertFieldsToString":true},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"835b1e19-c429-4814-92e4-d15dd031ac76","name":"📲 Skipped","type":"n8n-nodes-base.telegram","position":[3424,800],"webhookId":"84eb8437-e0ba-4d1e-8cb3-3f8f6b19416d","parameters":{"text":"=⏭️ *Lead Skipped*\n👤 {{ $json.leadName }} @ {{ $json.company }}\n📊 Score: {{ $json.score }}/100\n💬 {{ $json.overallAssessment }}","chatId":"YOUR_TELEGRAM_CHAT_ID","additionalFields":{"parse_mode":"Markdown"}},"typeVersion":1.2},{"id":"c4316023-e077-4889-ac3d-86ad9059d458","name":"💤 No New Leads","type":"n8n-nodes-base.code","position":[1824,848],"parameters":{"jsCode":"return { json: { status: 'no_new_leads', checkedAt: new Date().toLocaleString() } };"},"typeVersion":2},{"id":"9da28257-a906-4425-81f9-a11fde5a8864","name":"⏰ Every 2hrs — Follow-ups","type":"n8n-nodes-base.scheduleTrigger","position":[928,1264],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 10,12,14,16 * * 1-5"}]}},"typeVersion":1.2},{"id":"cffcf037-6615-4705-8a8f-49dbbcbe1e40","name":"📋 Read Sheet (Follow-ups)","type":"n8n-nodes-base.googleSheets","position":[1152,1264],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"44cea630-cb7a-461f-9459-0b602f839d00","name":"🔍 Find Follow-ups","type":"n8n-nodes-base.code","position":[1376,1264],"parameters":{"jsCode":"const allRows = $input.all();\nconst now = new Date();\nconst actions = [];\n\n// ⚠️ CHANGE THIS to your name\nconst senderName = 'YOUR_NAME';\n\nfunction formatBody(rawContent, firstName) {\n  if (!rawContent) return '';\n  let body = rawContent;\n  body = body.replace(/^Subject:.*?\\n\\n?/i, '');\n  body = body.replace(/^Subject:.*?\\n/i, '');\n  body = body.replace(/\\\\n/g, '\\n');\n  body = body.replace(/\\\\\\\\n/g, '\\n');\n  body = body.replace(/\\*\\*/g, '');\n  body = body.replace(/^#+\\s/gm, '');\n  body = body.replace(/\\[YOUR NAME\\]/gi, senderName);\n  body = body.replace(/\\[Your Name\\]/g, senderName);\n  body = body.replace(/YourName/g, senderName);\n  body = body.replace(/\\n\\n?(Best|Cheers|Thanks|Thank you|Regards|Kind regards|Warm regards|Sincerely|Talk soon|All the best),?\\s*\\n\\s*[A-Z][a-zA-Z]*(\\s+[A-Z][a-zA-Z]*)?\\s*(\\n\\n?(Best|Cheers|Thanks|Thank you|Regards|Kind regards|Warm regards|Sincerely|Talk soon|All the best),?\\s*\\n\\s*(\\[YOUR NAME\\]|YourName|[A-Z][a-zA-Z]*(\\s+[A-Z][a-zA-Z]*)?))?$/i, '');\n  body = body.replace(/\\n\\n?(Best|Cheers|Thanks|Regards|Sincerely|Talk soon),?\\s*$/i, '');\n  body = body.trimEnd();\n  if (!/^(Hi|Hey|Hello|Dear|Good)\\s/i.test(body.trim())) {\n    body = `Hi ${firstName},\\n\\n${body}`;\n  }\n  body = body + `\\n\\nBest,\\n${senderName}`;\n  body = body.replace(/\\n{4,}/g, '\\n\\n\\n').trim();\n  return body;\n}\n\nfunction toHTML(text) {\n  let html = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\\n\\n/g, '</p><p>').replace(/\\n/g, '<br>');\n  return '<div style=\"font-family: Arial, sans-serif; font-size: 14px; color: #333; line-height: 1.6;\"><p>' + html + '</p></div>';\n}\n\nfor (let i = 0; i < allRows.length; i++) {\n  const r = allRows[i].json;\n  const name = r['Lead Name'] || '';\n  const email = r['Email'] || r['email'] || '';\n  const company = r['Company'] || '';\n  const status = (r['Status'] || '').toLowerCase().trim();\n  const firstName = (name || '').split(' ')[0] || 'there';\n\n  if (!name || !email) continue;\n  if (['low_fit_skipped', 'sequence_complete', 'replied', 'new'].includes(status)) continue;\n\n  const email1SentStr = (r['email 1 sent date'] || '').toString().trim();\n  const email2SentStr = (r['email 2 sent date '] || r['email 2 sent date'] || '').toString().trim();\n  const email3SentStr = (r['email 3 sent date'] || '').toString().trim();\n\n  if (!email1SentStr) continue;\n\n  const email1SentDate = new Date(email1SentStr);\n  if (isNaN(email1SentDate.getTime())) continue;\n\n  const daysSinceEmail1 = (now - email1SentDate) / (1000 * 60 * 60 * 24);\n\n  if (!email2SentStr && daysSinceEmail1 >= 3) {\n    const subject = r['email 2 subject'] || ('Re: ' + (r['email 1subject'] || `Following up — ${company}`).replace(/^Re:\\s*/i, ''));\n    const body = formatBody(\n      r['email 2 body'] || `Hi ${firstName},\\n\\nI had another thought about how we might help ${company}.\\n\\nWould it make sense to connect briefly?`,\n      firstName\n    );\n    actions.push({ json: {\n      action: 'send_email_2', leadName: name, email: email, company: company,\n      subject: subject, body: body, htmlBody: toHTML(body), emailNumber: 2,\n      daysSinceEmail1: Math.round(daysSinceEmail1 * 10) / 10\n    }});\n  }\n  else if (email2SentStr && !email3SentStr && daysSinceEmail1 >= 7) {\n    const subject = r['email 3 sub'] || ('Re: ' + (r['email 1subject'] || `Following up — ${company}`).replace(/^Re:\\s*/i, ''));\n    const body = formatBody(\n      r['email 3 body'] || `Hi ${firstName},\\n\\nI know you're busy, so I'll keep this short.\\n\\nIf timing isn't right, no worries at all.\\n\\nWishing you and ${company} all the best.`,\n      firstName\n    );\n    actions.push({ json: {\n      action: 'send_email_3', leadName: name, email: email, company: company,\n      subject: subject, body: body, htmlBody: toHTML(body), emailNumber: 3,\n      daysSinceEmail1: Math.round(daysSinceEmail1 * 10) / 10\n    }});\n  }\n}\n\nif (actions.length === 0) {\n  return [{ json: { hasActions: false, message: 'No follow-ups needed right now.', totalRowsChecked: allRows.length, checkedAt: new Date().toLocaleString() }}];\n}\n\nreturn actions;"},"typeVersion":2},{"id":"efbc486b-0d8f-4001-bbe4-63cf0ca2dbdd","name":"📧 Has Follow-ups?","type":"n8n-nodes-base.if","position":[1600,1264],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"has-action","operator":{"type":"string","operation":"notEmpty"},"leftValue":"={{ $json.action }}","rightValue":""}]}},"typeVersion":2.2},{"id":"f6c8fed2-d1bc-43d4-bb79-87517538c114","name":"📧 Send Follow-up","type":"n8n-nodes-base.gmail","position":[1824,1168],"webhookId":"8e8967ef-2cf3-45f2-ad9d-6c7258af3472","parameters":{"sendTo":"={{ $json.email }}","message":"={{ $json.htmlBody }}","options":{"appendAttribution":false},"subject":"={{ $json.subject }}"},"typeVersion":2.1},{"id":"999b991c-87ad-402d-a9c3-2ded4af66698","name":"📋 Prepare Update","type":"n8n-nodes-base.code","position":[2048,1168],"parameters":{"jsCode":"const data = $('📧 Has Follow-ups?').item.json;\nconst nowISO = new Date().toISOString();\n\nconst update = { 'Lead Name': data.leadName };\n\nif (data.emailNumber === 2) {\n  update['Status'] = 'email_2_sent';\n  update['email 2 sent date '] = nowISO;\n  update['email 2 subject'] = data.subject;\n  update['email 2 body'] = data.body;\n  update['email 2 body html'] = data.htmlBody;\n} else if (data.emailNumber === 3) {\n  update['Status'] = 'sequence_complete';\n  update['email 3 sent date'] = nowISO;\n  update['email 3 sub'] = data.subject;\n  update['email 3 body'] = data.body;\n  update['email 3 body html'] = data.htmlBody;\n}\n\nreturn { json: update };"},"typeVersion":2},{"id":"852f7db1-c97c-4c6e-9cd6-1f4ff55b382d","name":"✅ Mark Follow-up Sent","type":"n8n-nodes-base.googleSheets","position":[2272,1168],"parameters":{"columns":{"value":{"Status":"={{ $json.Status }}","Lead Name":"={{ $json['Lead Name'] }}","email 3 sub":"={{ $json['email 3 sub'] || '' }}","email 2 body":"={{ $json['email 2 body'] || '' }}","email 3 body":"={{ $json['email 3 body'] || '' }}","email 2 subject":"={{ $json['email 2 subject'] || '' }}","email 2 body html":"={{ $json['email 2 body html'] || '' }}","email 3 body html":"={{ $json['email 3 body html'] || '' }}","email 3 sent date":"={{ $json['email 3 sent date'] || '' }}","email 2 sent date ":"={{ $json['email 2 sent date '] || '' }}"},"schema":[{"id":"Lead Name","type":"string","display":true,"removed":false,"required":false,"displayName":"Lead Name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Status","type":"string","display":true,"required":false,"displayName":"Status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 sent date ","type":"string","display":true,"required":false,"displayName":"email 2 sent date ","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 subject","type":"string","display":true,"required":false,"displayName":"email 2 subject","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 body","type":"string","display":true,"required":false,"displayName":"email 2 body","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 2 body html","type":"string","display":true,"required":false,"displayName":"email 2 body html","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 sent date","type":"string","display":true,"required":false,"displayName":"email 3 sent date","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 sub","type":"string","display":true,"required":false,"displayName":"email 3 sub","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 body","type":"string","display":true,"required":false,"displayName":"email 3 body","defaultMatch":false,"canBeUsedToMatch":true},{"id":"email 3 body html","type":"string","display":true,"required":false,"displayName":"email 3 body html","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Lead Name"],"attemptToConvertTypes":false,"convertFieldsToString":true},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"9149478f-d8fa-4c9a-8c9c-7f3095661c23","name":"📲 Follow-up Sent","type":"n8n-nodes-base.telegram","position":[2272,1008],"webhookId":"7b43efc5-2b6d-47b4-a525-0012c7043224","parameters":{"text":"=📧 *Follow-up Email {{ $('📧 Has Follow-ups?').item.json.emailNumber }} Sent*\n\n👤 {{ $('📧 Has Follow-ups?').item.json.leadName }} @ {{ $('📧 Has Follow-ups?').item.json.company }}\n📨 {{ $('📧 Has Follow-ups?').item.json.email }}\n📝 {{ $('📧 Has Follow-ups?').item.json.subject }}\n\n{{ $('📧 Has Follow-ups?').item.json.emailNumber === 3 ? '🏁 Sequence complete!' : '⏳ Next follow-up scheduled.' }}\n⏰ {{ new Date().toLocaleString() }}","chatId":"YOUR_TELEGRAM_CHAT_ID","additionalFields":{"parse_mode":"Markdown"}},"typeVersion":1.2},{"id":"19415433-ff65-4a27-94e6-7c86cacf41b8","name":"💤 Nothing Pending","type":"n8n-nodes-base.code","position":[1824,1360],"parameters":{"jsCode":"return { json: { status: 'no_followups', checkedAt: new Date().toLocaleString() } };"},"typeVersion":2},{"id":"f5e432ab-8110-4c6b-a121-2aaa1d6d3826","name":"Ollama Scorer","type":"@n8n/n8n-nodes-langchain.lmChatOllama","position":[2352,880],"parameters":{"model":"YOUR_MODEL_NAME","options":{"temperature":0.3}},"typeVersion":1},{"id":"227b7180-940f-496c-9762-9690f7782591","name":"Ollama Writer","type":"@n8n/n8n-nodes-langchain.lmChatOllama","position":[3152,624],"parameters":{"model":"YOUR_MODEL_NAME","options":{"temperature":0.7}},"typeVersion":1},{"id":"4e08504a-2411-4ce8-a17f-9281ec0c34e6","name":"⏰ Every 2hrs — Reply Check","type":"n8n-nodes-base.scheduleTrigger","position":[928,1744],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"30 9,11,13,15,17 * * 1-5"}]}},"typeVersion":1.2},{"id":"6c1293fa-42f5-485c-9568-179bf8e55414","name":"📋 Read Sheet (Replies)","type":"n8n-nodes-base.googleSheets","position":[1152,1744],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"2a290c73-5488-4b01-8bfa-93879cbe60e0","name":"🔍 Filter Active Leads","type":"n8n-nodes-base.code","position":[1376,1744],"parameters":{"jsCode":"const allRows = $input.all();\nconst activeLeads = [];\n\n// ⚠️ REPLACE WITH YOUR GMAIL ADDRESS\nconst MY_GMAIL = 'user@example.com';\n\nfor (let i = 0; i < allRows.length; i++) {\n  const r = allRows[i].json;\n  const name = r['Lead Name'] || '';\n  const email = (r['Email'] || r['email'] || '').trim().toLowerCase();\n  const company = r['Company'] || '';\n  const status = (r['Status'] || '').toLowerCase().trim();\n\n  if (!name || !email) continue;\n\n  const activeStatuses = ['email_1_sent', 'email_2_sent', 'sequence_complete'];\n  if (!activeStatuses.includes(status)) continue;\n\n  const email1SentStr = (r['email 1 sent date'] || '').toString().trim();\n  if (!email1SentStr) continue;\n\n  activeLeads.push({\n    json: {\n      leadName: name,\n      email: email,\n      company: company,\n      status: status,\n      email1SentDate: email1SentStr,\n      myGmail: MY_GMAIL,\n      rowIndex: i + 2\n    }\n  });\n}\n\nif (activeLeads.length === 0) {\n  return [{ json: { hasActiveLeads: false, message: 'No active leads to check for replies.', checkedAt: new Date().toLocaleString() } }];\n}\n\nreturn activeLeads;"},"typeVersion":2},{"id":"e9b61105-f943-4b5d-8edd-2837a0fec3d3","name":"📬 Has Active Leads?","type":"n8n-nodes-base.if","position":[1600,1744],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"has-active","operator":{"type":"string","operation":"notEmpty"},"leftValue":"={{ $json.email }}","rightValue":""}]}},"typeVersion":2.2},{"id":"3a7dc4af-95a5-4434-990e-4e2fc37a4b84","name":"🔎 Search Gmail Replies","type":"n8n-nodes-base.gmail","position":[1824,1648],"webhookId":"49405ae9-5847-4dd7-a81f-9a41dcb9ab3c","parameters":{"limit":30,"simple":false,"filters":{"q":"=from:{{ $json.email }} in:inbox newer_than:30d -in:sent","includeSpamTrash":false},"options":{},"operation":"getAll"},"typeVersion":2.1},{"id":"a9320a6b-095c-442b-ae07-d7422554dc99","name":"📩 Check Reply Results","type":"n8n-nodes-base.code","position":[2048,1648],"parameters":{"jsCode":"const lead = $('📬 Has Active Leads?').item.json;\nconst gmailResults = $input.all();\n\n// ⚠️ REPLACE WITH YOUR GMAIL ADDRESS\nconst MY_GMAIL = (lead.myGmail || 'user@example.com').toLowerCase().trim();\n\nfunction safeParseDate(val) {\n  if (val === null || val === undefined || val === '') return null;\n  const str = String(val).trim();\n  if (!str || str === '0' || str === 'undefined' || str === 'null') return null;\n\n  if (/^\\d{10,13}$/.test(str)) {\n    const num = parseInt(str, 10);\n    const ms = str.length <= 10 ? num * 1000 : num;\n    const d = new Date(ms);\n    if (!isNaN(d.getTime()) && d.getFullYear() > 2000 && d.getFullYear() < 2100) return d;\n  }\n\n  try {\n    const d1 = new Date(str);\n    if (!isNaN(d1.getTime()) && d1.getFullYear() > 2000 && d1.getFullYear() < 2100) return d1;\n  } catch(e) {}\n\n  const num = Number(val);\n  if (!isNaN(num) && num > 1+1234567890) {\n    const ms = num > 1+1234567890 ? num : num * 1000;\n    try {\n      const d2 = new Date(ms);\n      if (!isNaN(d2.getTime()) && d2.getFullYear() > 2000 && d2.getFullYear() < 2100) return d2;\n    } catch(e) {}\n  }\n\n  return null;\n}\n\nfunction extractEmail(fromStr) {\n  if (!fromStr) return '';\n  const s = String(fromStr).toLowerCase().trim();\n  const match = s.match(/<([^>]+)>/);\n  if (match) return match[1].trim();\n  if (s.includes('@')) return s.trim();\n  return s;\n}\n\nconst email1SentDate = safeParseDate(lead.email1SentDate);\n\nif (!email1SentDate) {\n  return [{ json: {\n    hasReply: false, leadName: lead.leadName || '', email: lead.email || '',\n    company: lead.company || '', currentStatus: lead.status || '',\n    replyDate: '', replySubject: '', replySnippet: '',\n    debug: 'Could not parse email1SentDate: ' + String(lead.email1SentDate)\n  }}];\n}\n\nif (!gmailResults || gmailResults.length === 0) {\n  return [{ json: {\n    hasReply: false, leadName: lead.leadName || '', email: lead.email || '',\n    company: lead.company || '', currentStatus: lead.status || '',\n    replyDate: '', replySubject: '', replySnippet: ''\n  }}];\n}\n\nconst leadEmail = (lead.email || '').toLowerCase().trim();\nlet replyFound = false;\nlet replyDate = '';\nlet replySubject = '';\nlet replySnippet = '';\n\nfor (const msg of gmailResults) {\n  const m = msg.json || {};\n\n  const labels = m.labelIds || m.labels || [];\n  const labelArr = Array.isArray(labels) ? labels : [String(labels)];\n  const labelStr = labelArr.join(',').toUpperCase();\n  if (labelStr.includes('SENT') && !labelStr.includes('INBOX')) continue;\n\n  const fromRaw = m.from || m.From || m.sender || m.Sender || '';\n  const senderEmail = extractEmail(fromRaw);\n\n  if (senderEmail === MY_GMAIL) continue;\n  if (!senderEmail.includes(leadEmail) && !leadEmail.includes(senderEmail)) continue;\n\n  const msgDate = safeParseDate(m.internalDate)\n    || safeParseDate(m.date)\n    || safeParseDate(m.Date)\n    || safeParseDate(m.receivedDate)\n    || null;\n\n  if (!msgDate) continue;\n  if (msgDate <= email1SentDate) continue;\n\n  if (extractEmail(fromRaw) === MY_GMAIL) continue;\n\n  replyFound = true;\n  replyDate = msgDate.toISOString();\n  replySubject = m.subject || m.Subject || '(no subject)';\n  replySnippet = (m.snippet || m.textPlain || m.text || m.body || '').toString().substring(0, 300);\n  break;\n}\n\nreturn [{ json: {\n  hasReply: replyFound, leadName: lead.leadName || '', email: lead.email || '',\n  company: lead.company || '', currentStatus: lead.status || '',\n  replyDate: replyDate, replySubject: replySubject, replySnippet: replySnippet\n}}];"},"typeVersion":2},{"id":"83fe6612-0f68-486a-94fd-0277ddc815d1","name":"💬 Reply Found?","type":"n8n-nodes-base.if","position":[2272,1648],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"has-reply","operator":{"type":"boolean","operation":"true"},"leftValue":"={{ $json.hasReply }}","rightValue":true}]}},"typeVersion":2.2},{"id":"91a4af5a-cdbd-42c6-bdc9-0eb1245acb04","name":"✅ Mark Replied in Sheet","type":"n8n-nodes-base.googleSheets","position":[2496,1536],"parameters":{"columns":{"value":{"Status":"replied","Lead Name":"={{ $json.leadName }}","Reply Date":"={{ $json.replyDate }}","Reply Snippet":"={{ $json.replySnippet }}","Reply Subject":"={{ $json.replySubject }}"},"schema":[{"id":"Lead Name","type":"string","display":true,"removed":false,"required":false,"displayName":"Lead Name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Status","type":"string","display":true,"required":false,"displayName":"Status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Reply Date","type":"string","display":true,"required":false,"displayName":"Reply Date","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Reply Subject","type":"string","display":true,"required":false,"displayName":"Reply Subject","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Reply Snippet","type":"string","display":true,"required":false,"displayName":"Reply Snippet","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Lead Name"],"attemptToConvertTypes":false,"convertFieldsToString":true},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"YOUR_SHEET_GID","cachedResultName":"Leads"},"documentId":{"__rl":true,"mode":"id","value":"YOUR_GOOGLE_SHEET_ID"}},"typeVersion":4.6},{"id":"46f06680-5f22-4431-9a79-a934fc9846b8","name":"📲 Reply Alert! 🎉","type":"n8n-nodes-base.telegram","position":[2496,1376],"webhookId":"ef3e8df5-7df9-48f4-ab80-e7009cec3c7b","parameters":{"text":"=🎉 *REPLY DETECTED — Auto-SDR*\n\n👤 {{ $('💬 Reply Found?').item.json.leadName }}\n🏢 {{ $('💬 Reply Found?').item.json.company }}\n📧 From: {{ $('💬 Reply Found?').item.json.email }}\n📝 Subject: {{ $('💬 Reply Found?').item.json.replySubject }}\n\n💬 Preview:\n_{{ $('💬 Reply Found?').item.json.replySnippet }}_\n\n🛑 Sequence stopped. Follow up manually!\n📅 {{ $('💬 Reply Found?').item.json.replyDate }}\n⏰ Detected: {{ new Date().toLocaleString() }}","chatId":"YOUR_TELEGRAM_CHAT_ID","additionalFields":{"parse_mode":"Markdown"}},"typeVersion":1.2},{"id":"6985015c-8601-4beb-86d1-7a5c2723231a","name":"💤 No Reply Yet","type":"n8n-nodes-base.code","position":[2496,1744],"parameters":{"jsCode":"return { json: { status: 'no_reply', leadName: $json.leadName || '', email: $json.email || '', checkedAt: new Date().toLocaleString() } };"},"typeVersion":2},{"id":"6f41120c-93b1-43a7-98cc-8e54bafa2a03","name":"💤 No Active Leads","type":"n8n-nodes-base.code","position":[1824,1840],"parameters":{"jsCode":"return { json: { status: 'no_active_leads_to_check', checkedAt: new Date().toLocaleString() } };"},"typeVersion":2}],"active":false,"pinData":{},"settings":{"binaryMode":"separate","availableInMCP":false,"executionOrder":"v1"},"versionId":"5cffe5e9-b1db-48f0-b5bc-7ac32e366b44","connections":{"📊 Pursue?":{"main":[[{"node":"✍️ AI Email Writer","type":"main","index":0}],[{"node":"⏭️ Mark Skipped","type":"main","index":0}]]},"Ollama Scorer":{"ai_languageModel":[[{"node":"📊 AI Lead Scorer","type":"ai_languageModel","index":0}]]},"Ollama Writer":{"ai_languageModel":[[{"node":"✍️ AI Email Writer","type":"ai_languageModel","index":0}]]},"🆕 Filter New":{"main":[[{"node":"🆕 Has Leads?","type":"main","index":0}]]},"🆕 Has Leads?":{"main":[[{"node":"🌐 Scrape Website","type":"main","index":0}],[{"node":"💤 No New Leads","type":"main","index":0}]]},"💬 Reply Found?":{"main":[[{"node":"✅ Mark Replied in Sheet","type":"main","index":0},{"node":"📲 Reply Alert! 🎉","type":"main","index":0}],[{"node":"💤 No Reply Yet","type":"main","index":0}]]},"📧 Send Email 1":{"main":[[{"node":"💾 Save + Mark Sent","type":"main","index":0},{"node":"📲 Email 1 Sent ✅","type":"main","index":0}]]},"🎯 Extract Score":{"main":[[{"node":"📊 Pursue?","type":"main","index":0}]]},"📄 Build Dossier":{"main":[[{"node":"📊 AI Lead Scorer","type":"main","index":0}]]},"⏭️ Mark Skipped":{"main":[[{"node":"📲 Skipped","type":"main","index":0}]]},"🌐 Scrape Website":{"main":[[{"node":"📄 Build Dossier","type":"main","index":0}]]},"📊 AI Lead Scorer":{"main":[[{"node":"🎯 Extract Score","type":"main","index":0}]]},"📋 Prepare Update":{"main":[[{"node":"✅ Mark Follow-up Sent","type":"main","index":0}]]},"📝 Extract Emails":{"main":[[{"node":"📧 Send Email 1","type":"main","index":0}]]},"📧 Send Follow-up":{"main":[[{"node":"📋 Prepare Update","type":"main","index":0},{"node":"📲 Follow-up Sent","type":"main","index":0}]]},"📧 Has Follow-ups?":{"main":[[{"node":"📧 Send Follow-up","type":"main","index":0}],[{"node":"💤 Nothing Pending","type":"main","index":0}]]},"🔍 Find Follow-ups":{"main":[[{"node":"📧 Has Follow-ups?","type":"main","index":0}]]},"📋 Read Sheet (New)":{"main":[[{"node":"🆕 Filter New","type":"main","index":0}]]},"⏰ 8 AM — New Leads":{"main":[[{"node":"📋 Read Sheet (New)","type":"main","index":0}]]},"✍️ AI Email Writer":{"main":[[{"node":"📝 Extract Emails","type":"main","index":0}]]},"📬 Has Active Leads?":{"main":[[{"node":"🔎 Search Gmail Replies","type":"main","index":0}],[{"node":"💤 No Active Leads","type":"main","index":0}]]},"📩 Check Reply Results":{"main":[[{"node":"💬 Reply Found?","type":"main","index":0}]]},"🔍 Filter Active Leads":{"main":[[{"node":"📬 Has Active Leads?","type":"main","index":0}]]},"📋 Read Sheet (Replies)":{"main":[[{"node":"🔍 Filter Active Leads","type":"main","index":0}]]},"🔎 Search Gmail Replies":{"main":[[{"node":"📩 Check Reply Results","type":"main","index":0}]]},"📋 Read Sheet (Follow-ups)":{"main":[[{"node":"🔍 Find Follow-ups","type":"main","index":0}]]},"⏰ Every 2hrs — Follow-ups":{"main":[[{"node":"📋 Read Sheet (Follow-ups)","type":"main","index":0}]]},"⏰ Every 2hrs — Reply Check":{"main":[[{"node":"📋 Read Sheet (Replies)","type":"main","index":0}]]}}},"lastUpdatedBy":1,"workflowInfo":{"nodeCount":44,"nodeTypes":{"n8n-nodes-base.if":{"count":5},"n8n-nodes-base.code":{"count":13},"n8n-nodes-base.gmail":{"count":3},"n8n-nodes-base.telegram":{"count":4},"n8n-nodes-base.stickyNote":{"count":5},"n8n-nodes-base.googleSheets":{"count":7},"@n8n/n8n-nodes-langchain.agent":{"count":2},"n8n-nodes-base.scheduleTrigger":{"count":3},"@n8n/n8n-nodes-langchain.lmChatOllama":{"count":2}}},"status":"published","readyToDemo":null,"user":{"name":"Tony Adijah","username":"togo","bio":"Automating the boring stuff so you don’t have to. 🤖 📐 n8n Workflows & Templates 🚀 Helping you save 10+ hours a week. 👇 Grab free workflows below.","verified":true,"links":["https://www.linkedin.com/in/tony-adijah-965903131/"],"avatar":"https://gravatar.com/avatar/e2635712dd01a1dae354636c1a925735948ada9697e9d55824f24558a3eab732?r=pg&d=retro&size=200"},"nodes":[{"id":18,"icon":"file:googleSheets.svg","name":"n8n-nodes-base.googleSheets","codex":{"data":{"alias":["CSV","Sheet","Spreadsheet","GS"],"resources":{"generic":[{"url":"https://n8n.io/blog/love-at-first-sight-ricardos-n8n-journey/","icon":"❤️","label":"Love at first sight: Ricardo’s n8n journey"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/","icon":"🧾","label":"Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/creating-triggers-for-n8n-workflows-using-polling/","icon":"⏲","label":"Creating triggers for n8n workflows using polling"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/migrating-community-metrics-to-orbit-using-n8n/","icon":"📈","label":"Migrating Community Metrics to Orbit using n8n"},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"url":"https://n8n.io/blog/how-honest-burgers-use-automation-to-save-100k-per-year/","icon":"🍔","label":"How Honest Burgers Use Automation to Save $100k per year"},{"url":"https://n8n.io/blog/how-a-digital-strategist-uses-n8n-for-online-marketing/","icon":"💻","label":"How a digital strategist uses n8n for online marketing"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/","icon":"📈","label":"How a Membership Development Manager automates his work and investments"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Data & Storage","Productivity"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\",\"output\"]","defaults":{"name":"Google Sheets"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNS42OSAxIDUyIDE3LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0OC4yOTMgNjBIMTIuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDkgNTYuMzEyVjQuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTIuNzA3IDF6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM1LjY5IDEgNTIgMTcuMjI1SDM5LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzkuMjExIDE3LjIyNSA1MiAyMi40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTIwLjEyIDMxLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMS42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzEuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNC42OSAwIDUxIDE2LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0Ny4yOTMgNTlIMTEuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDggNTUuMzEyVjMuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTEuNzA3IDB6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM0LjY5IDAgNTEgMTYuMjI1SDM4LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzguMjExIDE2LjIyNSA1MSAyMS40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE5LjEyIDMwLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMC42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzAuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjwvZz48L3N2Zz4="},"displayName":"Google Sheets","typeVersion":5,"nodeCategories":[{"id":3,"name":"Data & Storage"},{"id":4,"name":"Productivity"}]},{"id":20,"icon":"fa:map-signs","name":"n8n-nodes-base.if","codex":{"data":{"alias":["Router","Filter","Condition","Logic","Boolean","Branch"],"details":"The IF node can be used to implement binary conditional logic in your workflow. You can set up one-to-many conditions to evaluate each item of data being inputted into the node. That data will either evaluate to TRUE or FALSE and route out of the node accordingly.\n\nThis node has multiple types of conditions: Bool, String, Number, and Date & Time.","resources":{"generic":[{"url":"https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/","icon":"🏭","label":"Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"},{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/create-a-toxic-language-detector-for-telegram/","icon":"🤬","label":"Create a toxic language detector for Telegram in 4 step"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/","icon":"🔗","label":"How to build a low-code, self-hosted URL shortener in 3 steps"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/","icon":"🏷️","label":"How to automatically manage contributions to open-source projects"},{"url":"https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/","icon":" 🕸️","label":"How uProc scraped a multi-page website with a low-code workflow"},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.if/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"transform\"]","defaults":{"name":"If","color":"#408000"},"iconData":{"icon":"map-signs","type":"icon"},"displayName":"If","typeVersion":2,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":49,"icon":"file:telegram.svg","name":"n8n-nodes-base.telegram","codex":{"data":{"alias":["human","form","wait","hitl","approval"],"resources":{"generic":[{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/create-a-toxic-language-detector-for-telegram/","icon":"🤬","label":"Create a toxic language detector for Telegram in 4 step"},{"url":"https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/","icon":"🧾","label":"Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/world-poetry-day-workflow/","icon":"📜","label":"Celebrating World Poetry Day with a daily poem in Telegram"},{"url":"https://n8n.io/blog/using-automation-to-boost-productivity-in-the-workplace/","icon":"💪","label":"Using Automation to Boost Productivity in the Workplace"},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/creating-scheduled-text-affirmations-with-n8n/","icon":"🤟","label":"Creating scheduled text affirmations with n8n"},{"url":"https://n8n.io/blog/creating-telegram-bots-with-n8n-a-no-code-platform/","icon":"💬","label":"Creating Telegram Bots with n8n, a No-Code Platform"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/telegram/"}]},"categories":["Communication","HITL"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"HITL":["Human in the Loop"]}}},"group":"[\"output\"]","defaults":{"name":"Telegram"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB2aWV3Qm94PSIwIDAgNjYgNjYiPjx1c2UgeGxpbms6aHJlZj0iI2EiIHg9Ii41IiB5PSIuNSIvPjxzeW1ib2wgaWQ9ImEiIG92ZXJmbG93PSJ2aXNpYmxlIj48ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0ibm9uZSI+PHBhdGggZmlsbD0iIzM3YWVlMiIgZD0iTTAgMzJjMCAxNy42NzMgMTQuMzI3IDMyIDMyIDMyczMyLTE0LjMyNyAzMi0zMlM0OS42NzMgMCAzMiAwIDAgMTQuMzI3IDAgMzIiLz48cGF0aCBmaWxsPSIjYzhkYWVhIiBkPSJtMjEuNjYxIDM0LjMzOCAzLjc5NyAxMC41MDhzLjQ3NS45ODMuOTgzLjk4MyA4LjA2OC03Ljg2NCA4LjA2OC03Ljg2NGw4LjQwNy0xNi4yMzctMjEuMTE5IDkuODk4eiIvPjxwYXRoIGZpbGw9IiNhOWM2ZDgiIGQ9Im0yNi42OTUgMzcuMDM0LS43MjkgNy43NDZzLS4zMDUgMi4zNzMgMi4wNjggMGw0LjY0NC00LjIwMyIvPjxwYXRoIGQ9Im0yMS43MyAzNC43MTItNy44MDktMi41NDVzLS45MzItLjM3OC0uNjMzLTEuMjM3Yy4wNjItLjE3Ny4xODYtLjMyOC41NTktLjU4OCAxLjczMS0xLjIwNiAzMi4wMjgtMTIuMDk2IDMyLjAyOC0xMi4wOTZzLjg1Ni0uMjg4IDEuMzYxLS4wOTdjLjIzMS4wODguMzc4LjE4Ny41MDMuNTQ4LjA0NS4xMzIuMDcxLjQxMS4wNjguNjg5LS4wMDMuMjAxLS4wMjcuMzg2LS4wNDUuNjc4LS4xODQgMi45NzgtNS43MDYgMjUuMTk4LTUuNzA2IDI1LjE5OHMtLjMzIDEuMy0xLjUxNCAxLjM0NWMtLjQzMi4wMTYtLjk1Ni0uMDcxLTEuNTgyLS42MS0yLjMyMy0xLjk5OC0xMC4zNTItNy4zOTQtMTIuMTI2LTguNThhLjM0LjM0IDAgMCAxLS4xNDYtLjIzOWMtLjAyNS0uMTI1LjEwOC0uMjguMTA4LS4yOHMxMy45OC0xMi40MjcgMTQuMzUyLTEzLjczMWMuMDI5LS4xMDEtLjA3OS0uMTUxLS4yMjYtLjEwNy0uOTI5LjM0Mi0xNy4wMjUgMTAuNTA2LTE4LjgwMSAxMS42MjktLjEwNC4wNjYtLjM5NS4wMjMtLjM5NS4wMjMiLz48L2c+PC9zeW1ib2w+PC9zdmc+"},"displayName":"Telegram","typeVersion":1,"nodeCategories":[{"id":6,"name":"Communication"},{"id":28,"name":"HITL"}]},{"id":356,"icon":"file:gmail.svg","name":"n8n-nodes-base.gmail","codex":{"data":{"alias":["email","human","form","wait","hitl","approval"],"resources":{"generic":[{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"url":"https://n8n.io/blog/using-automation-to-boost-productivity-in-the-workplace/","icon":"💪","label":"Using Automation to Boost Productivity in the Workplace"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Communication","HITL"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"HITL":["Human in the Loop"]}}},"group":"[\"transform\"]","defaults":{"name":"Gmail"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMTkzIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZmlsbD0iIzQyODVGNCIgZD0iTTU4LjE4MiAxOTIuMDVWOTMuMTRMMjcuNTA3IDY1LjA3NyAwIDQ5LjUwNHYxMjUuMDkxYzAgOS42NTggNy44MjUgMTcuNDU1IDE3LjQ1NSAxNy40NTV6Ii8+PHBhdGggZmlsbD0iIzM0QTg1MyIgZD0iTTE5Ny44MTggMTkyLjA1aDQwLjcyN2M5LjY1OSAwIDE3LjQ1NS03LjgyNiAxNy40NTUtMTcuNDU1VjQ5LjUwNWwtMzEuMTU2IDE3LjgzNy0yNy4wMjYgMjUuNzk4eiIvPjxwYXRoIGZpbGw9IiNFQTQzMzUiIGQ9Im01OC4xODIgOTMuMTQtNC4xNzQtMzguNjQ3IDQuMTc0LTM2Ljk4OUwxMjggNjkuODY4bDY5LjgxOC01Mi4zNjQgNC42NyAzNC45OTItNC42NyA0MC42NDRMMTI4IDE0NS41MDR6Ii8+PHBhdGggZmlsbD0iI0ZCQkMwNCIgZD0iTTE5Ny44MTggMTcuNTA0VjkzLjE0TDI1NiA0OS41MDRWMjYuMjMxYzAtMjEuNTg1LTI0LjY0LTMzLjg5LTQxLjg5LTIwLjk0NXoiLz48cGF0aCBmaWxsPSIjQzUyMjFGIiBkPSJtMCA0OS41MDQgMjYuNzU5IDIwLjA3TDU4LjE4MiA5My4xNFYxNy41MDRMNDEuODkgNS4yODZDMjQuNjEtNy42NiAwIDQuNjQ2IDAgMjYuMjN6Ii8+PC9zdmc+"},"displayName":"Gmail","typeVersion":2,"nodeCategories":[{"id":6,"name":"Communication"},{"id":28,"name":"HITL"}]},{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":834,"icon":"file:code.svg","name":"n8n-nodes-base.code","codex":{"data":{"alias":["cpde","Javascript","JS","Python","Script","Custom Code","Function"],"details":"The Code node allows you to execute JavaScript in your workflow.","resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Code"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Code","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"id":839,"icon":"fa:clock","name":"n8n-nodes-base.scheduleTrigger","codex":{"data":{"alias":["Time","Scheduler","Polling","Cron","Interval"],"resources":{"generic":[],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"trigger\",\"schedule\"]","defaults":{"name":"Schedule Trigger","color":"#31C49F"},"iconData":{"icon":"clock","type":"icon"},"displayName":"Schedule Trigger","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":1119,"icon":"fa:robot","name":"@n8n/n8n-nodes-langchain.agent","codex":{"data":{"alias":["LangChain","Chat","Conversational","Plan and Execute","ReAct","Tools"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Agents","Root Nodes"]}}},"group":"[\"transform\"]","defaults":{"name":"AI Agent","color":"#404040"},"iconData":{"icon":"robot","type":"icon"},"displayName":"AI Agent","typeVersion":3,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1151,"icon":"file:ollama.svg","name":"@n8n/n8n-nodes-langchain.lmChatOllama","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatollama/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Language Models","Root Nodes"],"Language Models":["Chat Models (Recommended)"]}}},"group":"[\"transform\"]","defaults":{"name":"Ollama Chat Model"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNDEuMzMzIiBoZWlnaHQ9IjM0MS4zMzMiIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDE4MSAyNTYiPjxnIGZpbGw9IiM3RDdEODciPjxwYXRoIGQ9Ik0zNy43IDE5LjVjLTUuMiAxLjgtOC4zIDQuOS0xMS43IDExLjYtNC41IDguOS02LjIgMTkuMi01LjggMzUuNWwuMyAxNC4yLTUuOCA2LjFjLTE0LjggMTUuNS0xOC41IDM4LjctOS4yIDU3LjRsMy40IDYuOS0yIDQuNGMtMy40IDguMi01IDE2LjQtNSAyNi4zIDAgMTAuOCAxLjggMTkgNS44IDI2LjJsMi42IDQuOC0yLjEgNC45Yy0xLjIgMi43LTIuNiA3LjEtMy4yIDkuOC0xLjQgNi4yLTEuNSAyMi4xLS4xIDI1LjcgMSAyLjYgMS40IDIuNyA3LjYgMi43IDcuMyAwIDcgLjQgNS4zLTguNi0xLjUtOC4yLjItMTguOCA0LjItMjYuNiAzLjctNyAzLjgtMTAuNC41LTE0LjgtNC43LTYuNC02LjgtMTMuNi02LjktMjQtLjEtMTAuMyAxLjQtMTYgNi42LTI2LjEgMy4xLTYuMSAyLjktOC43LTEtMTIuMi0xLjEtMS0zLjEtNC4yLTQuMy03LTEuOS00LjItMi40LTYuOS0yLjMtMTQuMiAwLTExLjQgMi41LTE4LjMgOS41LTI2IDctNy42IDE0LjItMTEgMjMuOS0xMS4yIDQuMSAwIDcuOC0uMiA4LjItLjIuNC0uMSAxLjctMi4yIDIuOS00LjcgMy01LjkgOS42LTExLjkgMTYuNy0xNS4yIDQuOS0yLjMgNy0yLjcgMTQuNy0yLjcgNy45IDAgOS43LjQgMTQuOSAyLjkgNi44IDMuMyAxMy4zIDkuNCAxNS45IDE0LjggMSAyIDIuMyA0LjEgMyA0LjUuNi40IDQuNi44IDguNy44IDYuNy4xIDguMy41IDE0IDMuNiAxMi4zIDYuOCAxOS4zIDE4LjcgMTkuMyAzMy40LjEgNi43LS40IDktMi43IDE0LjItMS42IDMuNS0zLjUgNi44LTQuMyA3LjUtMy40IDIuOC0zLjUgNS44LS41IDExLjcgNS4yIDEwLjEgNi43IDE1LjggNi42IDI2LjEtLjEgMTAuNC0yLjIgMTcuNi02LjkgMjQtMy4zIDQuNC0zLjIgNy44LjUgMTQuOCA0IDcuOCA1LjcgMTguNCA0LjIgMjYuNi0xLjcgOS0yIDguNiA1LjMgOC42IDYuMiAwIDYuNi0uMSA3LjYtMi43IDEuNC0zLjYgMS4zLTE5LjUtLjEtMjUuNy0uNi0yLjctMi03LjEtMy4yLTkuOGwtMi4xLTQuOSAyLjYtNC44YzcuNi0xMy45IDcuOS0zNS45LjYtNTIuOGwtMi00LjcgMi41LTQuNmM5LjktMTguMyA2LjQtNDMuOS04LjEtNTkuMWwtNS44LTYuMS4zLTE0LjJjLjQtMTYuNC0xLjMtMjYuNi01LjgtMzUuNy02LjQtMTIuNi0xNy4yLTE1LjktMjYuMy03LjktNS40IDQuNy05LjIgMTMuOC0xMi4zIDI5LjgtLjMgMS40LTEgMi4yLTEuNyAxLjgtMTguMi04LTI5LjctOC41LTQ0LjMtMi4xTDY1IDU0LjlsLS40LTIuMkM2MSAzNC4yIDU2LjEgMjQuMiA0OSAyMC41Yy00LjMtMi4xLTcuNC0yLjQtMTEuMy0xbTcuNyAxNi44YzQuMiA3LjEgOC4xIDMwLjEgNS43IDMzLjYtLjUuOC0zLjEgMS42LTUuOCAxLjgtMi42LjItNi4yLjgtOCAxLjNsLTMuMS44LS43LTQuOWMtLjgtNS45LjItMTcuMiAyLjItMjQuOEMzNy4xIDM4LjQgNDAuNSAzMiA0MiAzMmMuNSAwIDIgMS45IDMuNCA0LjNtOTYuNS0xYzQgNi41IDYuOSAyMy45IDUuNiAzMy42bC0uNyA0LjktMy4xLS44Yy0xLjgtLjUtNS40LTEuMS04LTEuMy0yLjctLjItNS4zLTEtNS44LTEuOC0xLjItMS43LS4zLTE0LjEgMS43LTIyLjkgMS41LTYuNCA1LjctMTUgNy40LTE1IC40IDAgMS44IDEuNSAyLjkgMy4zIi8+PHBhdGggZD0iTTc3LjggMTE5LjljLTcuMyAyLjQtMTEuNiA1LjEtMTYuNSAxMC40LTUuNSA2LTcuNiAxMi03LjEgMjAuMS41IDcuNiAzLjUgMTIuOSAxMC42IDE4LjMgNi4yIDQuNyAxMi43IDYuMyAyNS43IDYuMyAxNy4yIDAgMjUuOC0zLjYgMzIuOS0xMy44IDQuMi01LjkgNC44LTE1LjUgMS42LTIzLTIuOS02LjgtMTEuMS0xNC4zLTE4LjgtMTcuMy04LTMuMS0yMC43LTMuNi0yOC40LTFtMjUuNyAxMGMxNi4xIDcuMSAxOS40IDIzLjIgNi42IDMxLjgtNC45IDMuMy05LjQgNC4zLTE5LjYgNC4zcy0xNC43LTEtMTkuNi00LjNjLTE3LjgtMTItMy4yLTM1LjYgMjEuMS0zNC4zIDMuOS4yIDguNiAxLjIgMTEuNSAyLjUiLz48cGF0aCBkPSJNODMuOCAxNDAuMWMtMi41IDEuNC0yLjIgNC40LjcgNi43IDIgMS42IDIuNCAyLjYgMS45IDQuOS0uNyAzLjYgMS41IDUuOCA1LjEgNC45IDIuMS0uNSAyLjUtMS4yIDIuNS00LjYgMC0yLjkuNS00LjIgMi01IDIuNy0xLjUgMi43LTYuNiAwLTcuNS0xLS4zLTIuOC0uMS00IC41LTEuNC43LTIuNi44LTMuOSAwLTIuMy0xLjItMi4yLTEuMi00LjMuMW0tNDQuMS0xOC45Yy0uOS43LTIuMyAzLTMuMiA1LTIuMSA1LjMtLjEgMTAuMyA0LjcgMTEuNiA0LjMgMS4xIDYgLjYgOS4yLTIuNyA0LTQuMSA0LjMtOC4xIDEuMS0xMS45LTIuMS0yLjUtMy40LTMuMi02LjQtMy4yLTIgMC00LjUuNi01LjQgMS4ybTg5LjggMmMtMy4yIDMuOC0yLjkgNy44IDEuMSAxMS45IDMuMiAzLjMgNC45IDMuOCA5LjIgMi43IDQuOS0xLjMgNi44LTYuMiA0LjYtMTEuOC0xLjktNC43LTMuOC02LTguNy02LTIuNyAwLTQuMS43LTYuMiAzLjIiLz48L2c+PC9zdmc+"},"displayName":"Ollama Chat Model","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]}],"categories":[{"id":38,"name":"Lead Nurturing"},{"id":49,"name":"AI Summarization"}],"image":[]}}