{
  "name": "Agent 5: Reply Tracker — labels & logs replies",
  "description": null,
  "active": false,
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "filters": {
          "q": "in:inbox newer_than:30d -from:mailer-daemon -from:postmaster -from:you@yourdomain.com"
        }
      },
      "id": "rt_trig",
      "name": "Poll Inbox (1m)",
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        416
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map(it=>{\n  const m=it.json;\n  const hdr=(n)=>{ if(m[n])return m[n]; if(m.headers&&m.headers[n.toLowerCase()])return m.headers[n.toLowerCase()];\n    const hs=(m.payload&&m.payload.headers)||[]; const h=hs.find(x=>(x.name||'').toLowerCase()===n.toLowerCase()); return h?h.value:''; };\n  let from=hdr('From')||m.from||'';\n  const email=((from.match(/<([^>]+)>/)||[,from])[1]||'').trim().toLowerCase();\n  const domain=(email.split('@')[1]||'').trim();\n  // Free-mail providers: a colleague can't be inferred from domain, so match the exact address only.\n  const FREE=new Set(['gmail.com','googlemail.com','yahoo.com','yahoo.co.in','outlook.com','hotmail.com','live.com','msn.com','icloud.com','me.com','aol.com','proton.me','protonmail.com','gmx.com','zoho.com','yandex.com']);\n  // For a real company domain, match ANY address at that domain so a reply from a\n  // different colleague (e.g. sabine@ when we emailed franchisesales@) still matches.\n  const match_pattern=(domain && !FREE.has(domain)) ? ('%@'+domain) : email;\n  return {json:{from_email:email, from_domain:domain, match_pattern, from_raw:from, subject:hdr('Subject')||m.subject||'',\n    snippet:(m.snippet||m.text||'').toString().slice(0,400), threadId:m.threadId||'', msgId:m.id||''}};\n}).filter(x=>x.json.from_email && !/(mailer-daemon|postmaster|no-?reply|notifications?@|google\\.com$)/.test(x.json.from_email));\n"
      },
      "id": "rt_extract",
      "name": "Extract Sender",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        416
      ]
    },
    {
      "parameters": {
        "operation": "getAll",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "to_email",
              "condition": "ilike",
              "keyValue": "={{ $json.match_pattern }}"
            }
          ]
        },
        "returnAll": true
      },
      "id": "rt_search",
      "name": "Match Outreach_Log",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        448,
        416
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "rt_if",
      "name": "Matched?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        672,
        416
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "condition": "eq",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "reply_received",
              "fieldValue": "={{ true }}"
            }
          ]
        }
      },
      "id": "rt_upd_out",
      "name": "Mark Reply (Outreach_Log)",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        128
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "tableId": "activity_log",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "summary",
              "fieldValue": "=Reply from {{ $('Match Outreach_Log').item.json.company }}"
            },
            {
              "fieldId": "workflow",
              "fieldValue": "Reply Tracker"
            },
            {
              "fieldId": "action",
              "fieldValue": "reply"
            },
            {
              "fieldId": "count",
              "fieldValue": 1
            },
            {
              "fieldId": "company",
              "fieldValue": "={{ $('Match Outreach_Log').item.json.company }}"
            },
            {
              "fieldId": "details",
              "fieldValue": "=Reply from {{ $('Extract Sender').item.json.from_email }} — {{ $('Extract Sender').item.json.subject }}"
            }
          ]
        }
      },
      "id": "rt_log",
      "name": "Log → Activity_Log",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        512
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "label",
        "operation": "create",
        "name": "outreach",
        "options": {}
      },
      "id": "rt_lbl_ensure",
      "name": "Ensure 'outreach' Label",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        896,
        704
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "label",
        "returnAll": true
      },
      "id": "rt_lbl_get",
      "name": "Get Gmail Labels",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1120,
        704
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "addLabels",
        "messageId": "={{ $('Extract Sender').item.json.msgId }}",
        "labelIds": [
          "={{ $('Get Gmail Labels').all().find(l => (l.json.name||'').toLowerCase()==='outreach')?.json.id }}"
        ]
      },
      "id": "rt_lbl_apply",
      "name": "Apply 'outreach' Label",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1344,
        704
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "condition": "eq",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "reply_date",
              "fieldValue": "={{ new Date().toISOString().slice(0,10) }}"
            }
          ]
        }
      },
      "id": "rt_stamp_replydate",
      "name": "Stamp Reply Date",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        320
      ],
      "continueOnFail": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "filters": {
          "q": "in:inbox newer_than:30d -from:mailer-daemon -from:postmaster -from:you@yourdomain.com"
        }
      },
      "id": "rt_trig",
      "name": "Poll Inbox (1m) B",
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        836
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map(it=>{\n  const m=it.json;\n  const hdr=(n)=>{ if(m[n])return m[n]; if(m.headers&&m.headers[n.toLowerCase()])return m.headers[n.toLowerCase()];\n    const hs=(m.payload&&m.payload.headers)||[]; const h=hs.find(x=>(x.name||'').toLowerCase()===n.toLowerCase()); return h?h.value:''; };\n  let from=hdr('From')||m.from||'';\n  const email=((from.match(/<([^>]+)>/)||[,from])[1]||'').trim().toLowerCase();\n  const domain=(email.split('@')[1]||'').trim();\n  // Free-mail providers: a colleague can't be inferred from domain, so match the exact address only.\n  const FREE=new Set(['gmail.com','googlemail.com','yahoo.com','yahoo.co.in','outlook.com','hotmail.com','live.com','msn.com','icloud.com','me.com','aol.com','proton.me','protonmail.com','gmx.com','zoho.com','yandex.com']);\n  // For a real company domain, match ANY address at that domain so a reply from a\n  // different colleague (e.g. sabine@ when we emailed franchisesales@) still matches.\n  const match_pattern=(domain && !FREE.has(domain)) ? ('%@'+domain) : email;\n  return {json:{from_email:email, from_domain:domain, match_pattern, from_raw:from, subject:hdr('Subject')||m.subject||'',\n    snippet:(m.snippet||m.text||'').toString().slice(0,400), threadId:m.threadId||'', msgId:m.id||''}};\n}).filter(x=>x.json.from_email && !/(mailer-daemon|postmaster|no-?reply|notifications?@|google\\.com$)/.test(x.json.from_email));\n"
      },
      "id": "rt_extract",
      "name": "Extract Sender B",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        836
      ]
    },
    {
      "parameters": {
        "operation": "getAll",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "to_email",
              "condition": "ilike",
              "keyValue": "={{ $json.match_pattern }}"
            }
          ]
        },
        "returnAll": true
      },
      "id": "rt_search",
      "name": "Match Outreach_Log B",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        448,
        836
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "rt_if",
      "name": "Matched? B",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        672,
        836
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "condition": "eq",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "reply_received",
              "fieldValue": "={{ true }}"
            }
          ]
        }
      },
      "id": "rt_upd_out",
      "name": "Mark Reply (Outreach_Log) B",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        548
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "tableId": "activity_log",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "summary",
              "fieldValue": "=Reply from {{ $('Match Outreach_Log B').item.json.company }}"
            },
            {
              "fieldId": "workflow",
              "fieldValue": "Reply Tracker"
            },
            {
              "fieldId": "action",
              "fieldValue": "reply"
            },
            {
              "fieldId": "count",
              "fieldValue": 1
            },
            {
              "fieldId": "company",
              "fieldValue": "={{ $('Match Outreach_Log B').item.json.company }}"
            },
            {
              "fieldId": "details",
              "fieldValue": "=Reply from {{ $('Extract Sender B').item.json.from_email }} — {{ $('Extract Sender B').item.json.subject }}"
            }
          ]
        }
      },
      "id": "rt_log",
      "name": "Log → Activity_Log B",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        932
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "label",
        "operation": "create",
        "name": "outreach",
        "options": {}
      },
      "id": "rt_lbl_ensure",
      "name": "Ensure 'outreach' Label B",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        896,
        1124
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "label",
        "returnAll": true
      },
      "id": "rt_lbl_get",
      "name": "Get Gmail Labels B",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1120,
        1124
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "addLabels",
        "messageId": "={{ $('Extract Sender B').item.json.msgId }}",
        "labelIds": [
          "={{ $('Get Gmail Labels B').all().find(l => (l.json.name||'').toLowerCase()==='outreach')?.json.id }}"
        ]
      },
      "id": "rt_lbl_apply",
      "name": "Apply 'outreach' Label B",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1344,
        1124
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "outreach_log",
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "condition": "eq",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "reply_date",
              "fieldValue": "={{ new Date().toISOString().slice(0,10) }}"
            }
          ]
        }
      },
      "id": "rt_stamp_replydate",
      "name": "Stamp Reply Date B",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        896,
        740
      ],
      "continueOnFail": true,
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Extract Sender": {
      "main": [
        [
          {
            "node": "Match Outreach_Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Outreach_Log": {
      "main": [
        [
          {
            "node": "Matched?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Matched?": {
      "main": [
        [
          {
            "node": "Mark Reply (Outreach_Log)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log → Activity_Log",
            "type": "main",
            "index": 0
          },
          {
            "node": "Ensure 'outreach' Label",
            "type": "main",
            "index": 0
          },
          {
            "node": "Stamp Reply Date",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Poll Inbox (1m)": {
      "main": [
        [
          {
            "node": "Extract Sender",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ensure 'outreach' Label": {
      "main": [
        [
          {
            "node": "Get Gmail Labels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Gmail Labels": {
      "main": [
        [
          {
            "node": "Apply 'outreach' Label",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Inbox (1m) B": {
      "main": [
        [
          {
            "node": "Extract Sender B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Sender B": {
      "main": [
        [
          {
            "node": "Match Outreach_Log B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Outreach_Log B": {
      "main": [
        [
          {
            "node": "Matched? B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Matched? B": {
      "main": [
        [
          {
            "node": "Mark Reply (Outreach_Log) B",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log → Activity_Log B",
            "type": "main",
            "index": 0
          },
          {
            "node": "Ensure 'outreach' Label B",
            "type": "main",
            "index": 0
          },
          {
            "node": "Stamp Reply Date B",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Ensure 'outreach' Label B": {
      "main": [
        [
          {
            "node": "Get Gmail Labels B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Gmail Labels B": {
      "main": [
        [
          {
            "node": "Apply 'outreach' Label B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "binaryMode": "separate"
  }
}