{
  "name": "05 — Reply Handler",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "gmail-push",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "wf05-0001",
      "name": "Gmail Push Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Decode Gmail Pub/Sub notification\nconst body = $json.body || $json;\nconst message = body.message || {};\nconst data = message.data || '';\n\nlet decoded = {};\ntry {\n  decoded = JSON.parse(Buffer.from(data, 'base64').toString('utf-8'));\n} catch(e) {\n  decoded = {};\n}\n\nreturn [{ json: { pubsub_decoded: decoded, email_address: decoded.emailAddress, history_id: decoded.historyId, raw_push: body } }];"
      },
      "id": "wf05-0002",
      "name": "Decode Pub/Sub Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://gmail.googleapis.com/gmail/v1/users/me/history?startHistoryId={{ $json.history_id }}&historyTypes=messageAdded&labelId=INBOX",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf05-0003",
      "name": "Fetch Gmail History",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const history = $json;\nconst messages = (history.history || []).flatMap(h => (h.messagesAdded || []).map(m => m.message));\nreturn messages.map(m => ({ json: { message_id: m.id, thread_id: m.threadId, prev: $('Decode Pub/Sub Message').item.json } }));"
      },
      "id": "wf05-0004",
      "name": "Extract New Message IDs",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "id": "wf05-0005",
      "name": "Split Messages",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://gmail.googleapis.com/gmail/v1/users/me/messages/{{ $json.message_id }}?format=full",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "options": {}
      },
      "id": "wf05-0006",
      "name": "Fetch Full Message",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1340,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const msg = $json;\nconst headers = msg.payload?.headers || [];\nconst getHeader = name => (headers.find(h => h.name.toLowerCase() === name) || {}).value || '';\n\nconst from_email = getHeader('from').match(/<([^>]+)>/)?.[1] || getHeader('from');\nconst subject = getHeader('subject');\nconst thread_id = msg.threadId;\n\n// Extract plain text body\nlet body_text = '';\nconst extractText = (parts) => {\n  for (const part of (parts || [])) {\n    if (part.mimeType === 'text/plain' && part.body?.data) {\n      body_text += Buffer.from(part.body.data, 'base64').toString('utf-8');\n    }\n    if (part.parts) extractText(part.parts);\n  }\n};\nif (msg.payload?.body?.data) {\n  body_text = Buffer.from(msg.payload.body.data, 'base64').toString('utf-8');\n} else {\n  extractText(msg.payload?.parts);\n}\n\n// Trim quoted history\nconst clean_body = body_text.split(/\\n>|\\nOn .* wrote:/)[0].trim();\n\nreturn [{ json: { from_email, subject, thread_id, clean_body, message_id: msg.id, raw_headers: headers } }];"
      },
      "id": "wf05-0007",
      "name": "Extract Reply Body",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1560,
        300
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT es.*, l.id as lead_id, l.company_name, l.research_artifact, l.state as lead_state,\n       lc.full_name, lc.role_title, lc.id as contact_id\nFROM leads.email_sends es\nJOIN leads.leads l ON l.id = es.lead_id\nJOIN leads.lead_contacts lc ON lc.id = es.contact_id\nWHERE es.gmail_thread_id = $1\nOR lc.email ILIKE '%' || $2 || '%'\nORDER BY es.sent_at DESC LIMIT 1",
        "additionalFields": {
          "queryParams": "={{ JSON.stringify([$json.thread_id, $json.from_email]) }}"
        }
      },
      "id": "wf05-0008",
      "name": "Match to Lead",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        1780,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "matched",
              "leftValue": "={{ $json.lead_id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0009",
      "name": "Lead Matched?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2000,
        300
      ]
    },
    {
      "parameters": {},
      "id": "wf05-0010",
      "name": "Unmatched Reply (ignore)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        2220,
        180
      ]
    },
    {
      "parameters": {
        "jsCode": "const lead_data = $json;\nconst reply_body = $('Extract Reply Body').item.json.clean_body;\n\nconst systemPrompt = `Classify this email reply. Return ONLY a JSON object with these exact keys:\n{\n  \"classification\": \"interested\" | \"objection\" | \"not_now\" | \"unsubscribe\" | \"pricing_inquiry\" | \"other\",\n  \"confidence\": 0.0-1.0,\n  \"key_signal\": \"one short phrase quoting the strongest signal from their reply\"\n}`;\n\nreturn [{ json: { ...lead_data, reply_body, groq_system: systemPrompt, groq_user: `Reply to classify:\\n\\n${reply_body}` } }];"
      },
      "id": "wf05-0011",
      "name": "Build Classification Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2220,
        420
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: 'llama-3.1-8b-instant', messages: [{ role: 'system', content: $json.groq_system }, { role: 'user', content: $json.groq_user }], temperature: 0.1, max_tokens: 200, response_format: { type: 'json_object' } }) }}",
        "options": {
          "timeout": 15000
        }
      },
      "id": "wf05-0012",
      "name": "Classify Reply (8B)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2440,
        420
      ]
    },
    {
      "parameters": {
        "jsCode": "const prev = $('Build Classification Prompt').item.json;\nlet cls = {};\ntry { cls = JSON.parse($json.choices[0].message.content); } catch(e) { cls = { classification: 'other', confidence: 0.5, key_signal: 'parse error' }; }\nreturn [{ json: { ...prev, classification: cls.classification, confidence: cls.confidence, key_signal: cls.key_signal } }];"
      },
      "id": "wf05-0013",
      "name": "Parse Classification",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2660,
        420
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "unsub",
              "leftValue": "={{ $json.classification }}",
              "rightValue": "unsubscribe",
              "operator": {
                "type": "string",
                "operation": "equal"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0014",
      "name": "Is Unsubscribe?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2880,
        420
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $json.from_email }}",
        "subject": "=Re: {{ $('Extract Reply Body').item.json.subject }}",
        "emailType": "text",
        "message": "Got it, removing you. Best of luck.",
        "options": {}
      },
      "id": "wf05-0015",
      "name": "Auto-Reply: Unsubscribe",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        3100,
        280
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE leads.leads SET state = 'closed_lost', updated_at = NOW() WHERE id = $1",
        "additionalFields": {
          "queryParams": "={{ JSON.stringify([$json.lead_id]) }}"
        }
      },
      "id": "wf05-0016",
      "name": "Mark Closed Lost",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        3320,
        280
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT value FROM leads.system_state WHERE key = 'reply_mode'",
        "additionalFields": {}
      },
      "id": "wf05-0017",
      "name": "Read reply_mode",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        3100,
        560
      ]
    },
    {
      "parameters": {
        "jsCode": "const classData = $('Parse Classification').item.json;\nconst ra = classData.research_artifact || {};\nconst calUrl = $env.CAL_DISCOVERY_URL || 'https://calendly.com/YOUR-LINK';\nconst senderName = $env.SENDER_NAME || 'Artenis';\n\nconst replyBody = classData.reply_body || '';\nconst classification = classData.classification || 'other';\n\nconst systemPrompt = `You are ${senderName}. Draft a natural reply to this email thread.\n\nContext:\n- You previously asked ${classData.company_name || 'them'} about: ${ra.the_specific_workflow || 'their manual workflow'}\n- Their reply: \"${replyBody}\"\n- Reply type: ${classification}\n\nRULES:\n- Sound like a real human having a conversation, not a sales rep\n- Match your tone to theirs — if they're brief, be brief\n\nIF they asked about your services, asked for a call, or clearly want help:\n  - Acknowledge what they said specifically (1 sentence)\n  - Briefly explain what you do in one concrete sentence (name the exact type of automation, not vague)\n  - End with: \"Want to jump on a quick call? ${calUrl}\"\n\nIF they described their situation but did not ask about your services:\n  - Acknowledge what they shared (1 sentence)\n  - Ask ONE follow-up question to understand their setup better\n  - NO Calendly link yet\n\nIF they asked for more info without committing:\n  - Give one specific, concrete example of what you automate for businesses like theirs\n  - End with: \"Worth a quick chat to see if it applies? ${calUrl}\"\n\n- Under 80 words total\n- NO corporate language: no \"I'd love to\", \"leverage\", \"streamline\", \"synergy\", \"touch base\"\n- Sign with just your first name\n\nOUTPUT: Plain text only. Just the email body. No subject line. No JSON.`;\n\nreturn [{ json: { ...classData, groq_system: systemPrompt, groq_user: 'Draft the reply now. Plain text only.' } }];"
      },
      "id": "wf05-0018",
      "name": "Build Draft Reply Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3320,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "fixed",
              "leftValue": "={{ $json.use_fixed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equal"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0019",
      "name": "Use Fixed Template?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        3540,
        560
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: 'llama-3.3-70b-versatile', messages: [{ role: 'system', content: $json.groq_system }, { role: 'user', content: $json.groq_user }], temperature: 0.3, max_tokens: 300 }) }}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "wf05-0020",
      "name": "Draft Reply (70B)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3760,
        420
      ]
    },
    {
      "parameters": {
        "jsCode": "const prev = $('Build Draft Reply Prompt').item.json;\nconst content = $json.choices?.[0]?.message?.content || '';\nreturn [{ json: { ...prev, draft_response: content } }];"
      },
      "id": "wf05-0021",
      "name": "Parse Draft",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3980,
        420
      ]
    },
    {
      "parameters": {
        "jsCode": "// Merge path: both fixed template and LLM draft arrive here\nconst d = $json;\n\n// Insert reply record\nreturn [{ json: {\n  ...d,\n  reply_id: `reply-${d.lead_id}-${Date.now()}`,\n  telegram_text: `📬 *New Reply — ${d.classification.toUpperCase()}*\\n\\n🏢 *${d.company_name}*\\n👤 ${d.full_name} · ${d.role_title}\\n📧 ${$('Extract Reply Body').item.json.from_email}\\n\\n💬 *Their message:*\\n${d.reply_body}\\n\\n📝 *Draft reply:*\\n${d.draft_response}`\n} }];"
      },
      "id": "wf05-0022",
      "name": "Prepare Telegram Approval",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4200,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "phase-b",
              "leftValue": "={{ $json.reply_mode }}",
              "rightValue": "phase_b",
              "operator": {
                "type": "string",
                "operation": "equal"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0023",
      "name": "Phase B?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4420,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "auto",
              "leftValue": "={{ $json.classification }}",
              "rightValue": "interested",
              "operator": {
                "type": "string",
                "operation": "equal"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0024",
      "name": "Auto-sendable Class?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4640,
        420
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://telegram-worker:8001/send",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ reply_id: $json.reply_id, text: $json.telegram_text }) }}",
        "options": {}
      },
      "id": "wf05-0025",
      "name": "Send to Telegram for Approval",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4640,
        700
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO leads.email_replies (lead_id, contact_id, send_id, raw_body, classification, confidence, key_signal, draft_response, approved_by_human)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, false)",
        "additionalFields": {
          "queryParams": "={{ JSON.stringify([$json.lead_id, $json.contact_id, $json.id, $json.reply_body, $json.classification, $json.confidence || 0.8, $json.key_signal, $json.draft_response]) }}"
        }
      },
      "id": "wf05-0026",
      "name": "Insert email_replies",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        4860,
        560
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE leads.leads SET state = 'replied', updated_at = NOW() WHERE id = $1",
        "additionalFields": {
          "queryParams": "={{ JSON.stringify([$json.lead_id]) }}"
        }
      },
      "id": "wf05-0027",
      "name": "Update Lead: Replied",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        5080,
        560
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "telegram-callback",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "wf05-0028",
      "name": "Telegram Callback Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        700
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "send-action",
              "leftValue": "={{ $json.action }}",
              "rightValue": "skip",
              "operator": {
                "type": "string",
                "operation": "notEqual"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf05-0029",
      "name": "Action is Send or Edit?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        460,
        700
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT er.*, l.id as lead_id, lc.email as to_email, es.subject as orig_subject\nFROM leads.email_replies er\nJOIN leads.leads l ON l.id = er.lead_id\nJOIN leads.lead_contacts lc ON lc.id = er.contact_id\nJOIN leads.email_sends es ON es.id = er.send_id\nWHERE er.id = (SELECT MAX(id) FROM leads.email_replies WHERE lead_id = (\n  SELECT lead_id FROM leads.email_replies ORDER BY id DESC LIMIT 1\n))\nLIMIT 1",
        "additionalFields": {}
      },
      "id": "wf05-0030",
      "name": "Fetch Reply Record",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        680,
        700
      ]
    },
    {
      "parameters": {
        "jsCode": "const callback = $('Telegram Callback Webhook').item.json;\nconst record = $json;\nconst senderName = $env.SENDER_NAME || 'Your Name';\nconst senderEmail = $env.SENDER_EMAIL || 'you@example.com';\nconst senderGithub = $env.SENDER_GITHUB || 'your-github';\n\nconst body = callback.action === 'edit'\n  ? callback.new_body + `\\n\\n— ${senderName} · ${senderEmail} · github.com/${senderGithub}`\n  : record.draft_response + `\\n\\n— ${senderName} · ${senderEmail} · github.com/${senderGithub}`;\n\nreturn [{ json: { ...record, final_body: body, to_email: record.to_email } }];"
      },
      "id": "wf05-0031",
      "name": "Prepare Approved Send",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        700
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $json.to_email }}",
        "subject": "=Re: {{ $json.orig_subject }}",
        "emailType": "text",
        "message": "={{ $json.final_body }}",
        "options": {}
      },
      "id": "wf05-0032",
      "name": "Send Approved Reply",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1120,
        700
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE leads.email_replies SET approved_by_human = true, sent_at = NOW() WHERE id = $1",
        "additionalFields": {
          "queryParams": "={{ JSON.stringify([$json.id]) }}"
        }
      },
      "id": "wf05-0033",
      "name": "Mark Reply Sent",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        1340,
        700
      ]
    }
  ],
  "connections": {
    "Gmail Push Webhook": {
      "main": [
        [
          {
            "node": "Decode Pub/Sub Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Decode Pub/Sub Message": {
      "main": [
        [
          {
            "node": "Fetch Gmail History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Gmail History": {
      "main": [
        [
          {
            "node": "Extract New Message IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract New Message IDs": {
      "main": [
        [
          {
            "node": "Split Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Messages": {
      "main": [
        [],
        [
          {
            "node": "Fetch Full Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Full Message": {
      "main": [
        [
          {
            "node": "Extract Reply Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Reply Body": {
      "main": [
        [
          {
            "node": "Match to Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match to Lead": {
      "main": [
        [
          {
            "node": "Lead Matched?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Matched?": {
      "main": [
        [
          {
            "node": "Unmatched Reply (ignore)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Classification Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Classification Prompt": {
      "main": [
        [
          {
            "node": "Classify Reply (8B)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Reply (8B)": {
      "main": [
        [
          {
            "node": "Parse Classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Classification": {
      "main": [
        [
          {
            "node": "Is Unsubscribe?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Unsubscribe?": {
      "main": [
        [
          {
            "node": "Auto-Reply: Unsubscribe",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Read reply_mode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auto-Reply: Unsubscribe": {
      "main": [
        [
          {
            "node": "Mark Closed Lost",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read reply_mode": {
      "main": [
        [
          {
            "node": "Build Draft Reply Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Draft Reply Prompt": {
      "main": [
        [
          {
            "node": "Use Fixed Template?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Use Fixed Template?": {
      "main": [
        [
          {
            "node": "Prepare Telegram Approval",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Draft Reply (70B)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft Reply (70B)": {
      "main": [
        [
          {
            "node": "Parse Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Draft": {
      "main": [
        [
          {
            "node": "Prepare Telegram Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Telegram Approval": {
      "main": [
        [
          {
            "node": "Phase B?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Phase B?": {
      "main": [
        [
          {
            "node": "Auto-sendable Class?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send to Telegram for Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auto-sendable Class?": {
      "main": [
        [
          {
            "node": "Send to Telegram for Approval",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Insert email_replies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to Telegram for Approval": {
      "main": [
        [
          {
            "node": "Insert email_replies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert email_replies": {
      "main": [
        [
          {
            "node": "Update Lead: Replied",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Callback Webhook": {
      "main": [
        [
          {
            "node": "Action is Send or Edit?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action is Send or Edit?": {
      "main": [
        [
          {
            "node": "Split Messages",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Reply Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Reply Record": {
      "main": [
        [
          {
            "node": "Prepare Approved Send",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Approved Send": {
      "main": [
        [
          {
            "node": "Send Approved Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Approved Reply": {
      "main": [
        [
          {
            "node": "Mark Reply Sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}
