{
  "id": "nwCxJfSOy2chwp10",
  "name": "Instagram Comment AI Reply (Telegram Approval)",
  "tags": [
    {
      "id": "uiGbrYRsIa2nPX3A",
      "name": "Template",
      "createdAt": "2026-02-24T19:47:53.477Z",
      "updatedAt": "2026-02-24T19:47:53.477Z"
    }
  ],
  "nodes": [
    {
      "id": "497ca266-431c-4260-8e5e-ea5b118a09f6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -1744
      ],
      "parameters": {
        "width": 480,
        "height": 704,
        "content": "## Instagram Comment AI Reply (Telegram Approval)\n\n### How it works\n\n1. The workflow retrieves recent Instagram media every 10 minutes and processes comments.\n2. New comments are evaluated to generate AI-based replies, which are then prepared for Telegram approval.\n3. Telegram notifications are sent for approval, and the decision is logged in Google Sheets.\n4. Approvals or rejections are processed, and the status is updated.\n5. Approved comments are automatically replied to on Instagram.\n6. Telegram updates are continuously monitored for approval replies.\n\n### Setup steps\n\n- [ ] Set up Instagram API credentials for fetching media and comments.\n- [ ] Configure OpenAI API access for generating AI replies.\n- [ ] Connect the Telegram bot to send and receive messages.\n- [ ] Set up Google Sheets API for logging and retrieving comment statuses.\n\n### Customization\n\nAdjust polling intervals, AI response generation parameters, or approval workflows as needed."
      },
      "typeVersion": 1
    },
    {
      "id": "3c92f561-024c-45ff-b2c3-52b2fa386b4c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -1904
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 560,
        "content": "## Initial trigger setup\n\nTriggers every 10 minutes to start the workflow and prepare environment."
      },
      "typeVersion": 1
    },
    {
      "id": "c20cc7e0-a598-456a-940c-5d962c78d779",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        -1664
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 320,
        "content": "## Fetch and prepare media\n\nFetches recent Instagram media and prepares comments for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "32a3cf0f-45d4-4618-aa35-ca72fd154a79",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        -1680
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 336,
        "content": "## Process comments\n\nSplits and processes comments, checks for self-comments, and identifies new comments."
      },
      "typeVersion": 1
    },
    {
      "id": "1f5cf358-2e7a-41ea-a0ff-f3b3796c66c1",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2272,
        -1680
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 336,
        "content": "## Generate AI reply\n\nGenerates AI-based replies for new comments and prepares data for Telegram."
      },
      "typeVersion": 1
    },
    {
      "id": "a7c0659c-920f-4293-9056-0472f1ef3aaf",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2736,
        -1680
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 336,
        "content": "## Telegram notification and logging\n\nSends approval requests to Telegram and logs the pending comment state."
      },
      "typeVersion": 1
    },
    {
      "id": "372b2729-3dac-4575-84b0-1c540cd3538f",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -1024
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 528,
        "content": "## Schedule and get updates\n\nTriggered schedule to process Telegram updates for approvals."
      },
      "typeVersion": 1
    },
    {
      "id": "f1e3ae8d-fa8a-4500-ac5e-84497cdf1ed0",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -1024
      ],
      "parameters": {
        "color": 7,
        "width": 912,
        "height": 528,
        "content": "## Telegram offsets and replies\n\nHandles Telegram updates by managing offsets and processing replies."
      },
      "typeVersion": 1
    },
    {
      "id": "4601c661-1f32-4c4a-8b53-ebeeb11cd83c",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        -1024
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 512,
        "content": "## Evaluate replies\n\nDetermines if a Telegram message is a reply and processes approved or rejected comments."
      },
      "typeVersion": 1
    },
    {
      "id": "99d03024-aa03-4774-9087-14237ca886d4",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        -1024
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 512,
        "content": "## Post and update status\n\nPosts replies to Instagram for approved comments and updates Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "27118dc3-5f4d-40dd-9128-32264383bb71",
      "name": "When Every 10 Min",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        192,
        -1664
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 10
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "003aa9dd-776e-471c-aa19-548de378b12f",
      "name": "Fetch Instagram Media",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Fetches your 10 most recent media items so we can check each for new comments.",
      "position": [
        768,
        -1504
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v19.0/17841476014473895/media",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "id,caption,timestamp"
            },
            {
              "name": "limit",
              "value": "10"
            },
            {
              "name": "access_token"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "notesInBoxView": false
    },
    {
      "id": "5ac22ffe-85c2-4149-9254-14066e5a0570",
      "name": "Split Media Data",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        992,
        -1504
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "8fb1cc55-312a-4205-a83f-076724426f8e",
      "name": "Fetch Media Comments",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1216,
        -1504
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/{{$json.id}}/comments",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "id,text,username,timestamp,from"
            },
            {
              "name": "access_token"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "43fe4cb8-e234-423d-85e8-d53e7c7412e2",
      "name": "Set Media Context",
      "type": "n8n-nodes-base.set",
      "notes": "Carries the media_id and caption forward so they survive the comments lookup.",
      "position": [
        1440,
        -1504
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b237256a-0ec4-4bb7-803e-1d11c74cc18b",
              "name": "comments",
              "type": "array",
              "value": "={{$json.data}}"
            },
            {
              "id": "c75adadd-9e5c-4a69-b513-f2ac079d7a23",
              "name": "media_id",
              "type": "string",
              "value": "={{$('Split Media Data').item.json.id}}"
            },
            {
              "id": "fa573287-f875-4e3b-b0e9-cb3de57b6dc6",
              "name": "post_caption",
              "type": "string",
              "value": "={{$('Split Media Data').item.json.caption}}"
            }
          ]
        }
      },
      "typeVersion": 3.4,
      "notesInBoxView": false
    },
    {
      "id": "56071982-1662-46c6-ad3c-793826dd304d",
      "name": "Split Comment Items",
      "type": "n8n-nodes-base.splitOut",
      "notes": "Each item is now a single comment, with media_id/post_caption attached as sibling fields.",
      "position": [
        1664,
        -1504
      ],
      "parameters": {
        "include": "allOtherFields",
        "options": {},
        "fieldToSplitOut": "comments"
      },
      "typeVersion": 1,
      "notesInBoxView": false
    },
    {
      "id": "32e84727-9c9d-4e7d-86df-ded40c8e0a6d",
      "name": "Exclude Self Comments",
      "type": "n8n-nodes-base.filter",
      "notes": "Drops comments authored by your own account. If IG omits 'username' for some commenters, you may need to also compare from.id against your IG business account id.",
      "position": [
        1888,
        -1504
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d0a8d132-80de-4967-9be2-a91dc11a3ece",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.comments.username }}",
              "rightValue": "=retrogames1337"
            },
            {
              "id": "9f8657f8-daae-4e72-93a6-b8a2bffd1f5a",
              "operator": {
                "type": "dateTime",
                "operation": "after"
              },
              "leftValue": "={{ $json.comments.timestamp }}",
              "rightValue": "={{ $now.minus(4880, 'minutes') }}"
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "notesInBoxView": false
    },
    {
      "id": "824c9123-f89f-4dd7-8bea-c81d7360d8df",
      "name": "If Comment Is New",
      "type": "n8n-nodes-base.if",
      "notes": "True (no existing rows found) = new comment, continue. False = already logged, skip.",
      "position": [
        2112,
        -1504
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "82796b3f-4123-4ac7-ab42-55e86a90ce6a",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ !$('Compile Logged IDs').first().json.ids.includes(String($json.comments.id)) }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "notesInBoxView": false
    },
    {
      "id": "ab9955e7-8f77-4509-b16e-9acdc3aae016",
      "name": "Skip Duplicate Comment",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2320,
        -1232
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "3f7c571a-0fa8-486b-ab02-d6c9df0a3f02",
      "name": "Post AI Reply",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Swap url/model/header for OpenAI or Anthropic if you'd rather not use Groq \u2014 the prompt logic stays the same.",
      "position": [
        2336,
        -1520
      ],
      "parameters": {
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ model: 'llama-3.3-70b-versatile', messages: [ { role: 'system', content: 'You write short, friendly Instagram comment replies for a retro gaming account. Max 2 short sentences. No hashtags, no emojis spam (1 emoji max), match the casual energy of the original comment. Use the post caption only as context, do not repeat it verbatim.' }, { role: 'user', content: 'Post caption: ' + ($json.post_caption || '') + '\\\\n\\\\nCommenter @' + $json.comments.username + ' wrote: ' + $json.comments.text + '\\\\n\\\\nWrite ONLY the reply text, nothing else.' } ], temperature: 0.7, max_tokens: 80 }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "notesInBoxView": false
    },
    {
      "id": "e03d66e3-4888-40d8-b98f-375ea3357ea2",
      "name": "Set Telegram & Sheets Data",
      "type": "n8n-nodes-base.set",
      "position": [
        2560,
        -1520
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "738c9452-22a7-4ef4-8697-8593b2468500",
              "name": "comment_id",
              "type": "string",
              "value": "={{$('Split Comment Items').item.json.comments.id}}"
            },
            {
              "id": "ce514a1f-bc1b-4cba-90d9-fd984855f31c",
              "name": "media_id",
              "type": "string",
              "value": "={{$('Split Comment Items').item.json.media_id}}"
            },
            {
              "id": "47e5dc43-5368-44b6-b8b9-806d17be43c1",
              "name": "username",
              "type": "string",
              "value": "={{$('Split Comment Items').item.json.comments.username}}"
            },
            {
              "id": "c269d575-2ded-466a-935d-7c3c09752397",
              "name": "comment_text",
              "type": "string",
              "value": "={{$('Split Comment Items').item.json.comments.text}}"
            },
            {
              "id": "226371f6-6a95-4bf8-bd18-e7168d14eabc",
              "name": "post_caption",
              "type": "string",
              "value": "={{$('Split Comment Items').item.json.post_caption}}"
            },
            {
              "id": "37689b81-52e0-4413-8bbb-67166e673651",
              "name": "ai_draft_reply",
              "type": "string",
              "value": "={{$json.choices[0].message.content.trim()}}"
            },
            {
              "id": "f3a6e004-8c7a-4c4d-98a0-5d338785c97d",
              "name": "caption_excerpt",
              "type": "string",
              "value": "={{ ($('Split Comment Items').item.json.post_caption || '').slice(0, 100) }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7c453348-3cde-45ab-bd8b-c55f9bbf9b96",
      "name": "Send Telegram Approval Request",
      "type": "n8n-nodes-base.telegram",
      "notes": "IMPORTANT: the reviewer must use Telegram's native Reply feature on this exact message, not just send a new message, so Flow B can match it.",
      "position": [
        2784,
        -1520
      ],
      "parameters": {
        "text": "=\ud83d\udcdd *Post:* {{$json.caption_excerpt}}\n\n\ud83d\udc64 *@{{$json.username}}*\n\ud83d\udcac \"{{$json.comment_text}}\"\n\n\ud83e\udd16 *Draft reply:*\n{{$json.ai_draft_reply}}\n\n\u2705 Reply YES to this message to post it\n\u274c Reply NO to reject and log it",
        "chatId": "=1386476744",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2,
      "notesInBoxView": false
    },
    {
      "id": "4cc728fe-8956-461f-993c-373644ca586a",
      "name": "Append Pending Comment",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2976,
        -1520
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "pending_review",
            "media_id": "={{$('Set Telegram & Sheets Data').item.json.media_id}}",
            "username": "={{$('Set Telegram & Sheets Data').item.json.username}}",
            "comment_id": "={{$('Set Telegram & Sheets Data').item.json.comment_id}}",
            "created_at": "={{$now.toISO()}}",
            "comment_text": "={{$('Set Telegram & Sheets Data').item.json.comment_text}}",
            "post_caption": "={{$('Set Telegram & Sheets Data').item.json.post_caption}}",
            "ai_draft_reply": "={{$('Set Telegram & Sheets Data').item.json.ai_draft_reply}}",
            "telegram_message_id": "={{ $json.result.message_id }}"
          },
          "schema": [
            {
              "id": "comment_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "comment_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "media_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "media_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "username",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "comment_text",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "comment_text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "post_caption",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "post_caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_draft_reply",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ai_draft_reply",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "telegram_message_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "telegram_message_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "resolved_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "resolved_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 582433129
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Olmrav835Z1jmhZQh6TsdWUxxw5HM-bd-h2_xpX72tU"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b505e93b-174c-4cd9-9fbb-c4b6da157199",
      "name": "Check Reply In Message",
      "type": "n8n-nodes-base.if",
      "notes": "Ignores any Telegram message that isn't a reply to a specific message (random chatter in the review chat).",
      "position": [
        1696,
        -736
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "89a255be-a357-48f3-aae4-6fe3694ffd43",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$json.message.reply_to_message}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "notesInBoxView": false
    },
    {
      "id": "1efd4ee2-ab90-43ed-a414-d7b7d4dd9989",
      "name": "Skip Non-reply Message",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1888,
        -656
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "61dae395-244f-4290-b109-4c63b791d0f7",
      "name": "Set Reply Information",
      "type": "n8n-nodes-base.set",
      "position": [
        1888,
        -880
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "dd5380cc-86dd-40d2-a2b5-64c90db5d80c",
              "name": "reply_to_message_id",
              "type": "string",
              "value": "={{$json.message.reply_to_message.message_id}}"
            },
            {
              "id": "bae2cab5-8779-4f32-aca5-804a0a1fba4c",
              "name": "decision_raw",
              "type": "string",
              "value": "={{$json.message.text}}"
            },
            {
              "id": "69f35f2b-90b1-48de-99eb-41ba17737616",
              "name": "decision",
              "type": "string",
              "value": "={{$json.message.text.trim().toUpperCase()}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c2a817b7-c16e-4217-bea1-36e439b7e095",
      "name": "Skip Non-match",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2480,
        -368
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "678a721b-99bc-4c26-93d4-0c2ae6978e01",
      "name": "Route by Approval",
      "type": "n8n-nodes-base.switch",
      "notes": "Output 0 = YES, Output 1 = NO, fallback = anything else (ignored). Reviewer must reply with exactly YES or NO.",
      "position": [
        2304,
        -880
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Approved",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "7a0692f4-88dd-4336-b426-20d265ab9031",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.decision}}",
                    "rightValue": "YES"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Rejected",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "5153f1cf-9f8d-43bd-9acc-f2dd2ba47db8",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.decision}}",
                    "rightValue": "NO"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.2,
      "notesInBoxView": false
    },
    {
      "id": "5a6a97d1-f7a8-48fe-9586-4e91f4d1ac27",
      "name": "Publish Reply on Instagram",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Posts the approved draft as a public reply to the original comment via the IG Graph API.",
      "position": [
        2608,
        -864
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/{{$json.comment_id}}/replies",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "message",
              "value": "={{$json.ai_draft_reply}}"
            },
            {
              "name": "access_token"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "notesInBoxView": false
    },
    {
      "id": "40d0de34-3e0f-4585-a744-ab48caf23470",
      "name": "Mark Approved in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2816,
        -864
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "approved",
            "comment_id": "={{ $('Route by Approval').item.json.comment_id }}",
            "resolved_at": "={{$now.toISO()}}"
          },
          "schema": [
            {
              "id": "comment_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "comment_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "media_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "media_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "username",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "comment_text",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "comment_text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "post_caption",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "post_caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_draft_reply",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "ai_draft_reply",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "telegram_message_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "telegram_message_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "resolved_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "resolved_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "comment_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 582433129
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Olmrav835Z1jmhZQh6TsdWUxxw5HM-bd-h2_xpX72tU"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "88bcf7ad-6338-485f-9876-6913a709316a",
      "name": "Mark Rejected in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Rejected comments are logged only \u2014 no Instagram action, per spec.",
      "position": [
        2672,
        -672
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "rejected",
            "comment_id": "={{ $('Route by Approval').item.json.comment_id }}",
            "row_number": 0,
            "resolved_at": "={{$now.toISO()}}"
          },
          "schema": [
            {
              "id": "comment_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "comment_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "media_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "media_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "username",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "comment_text",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "comment_text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "post_caption",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "post_caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_draft_reply",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "ai_draft_reply",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "telegram_message_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "telegram_message_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "resolved_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "resolved_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "comment_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 582433129
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Olmrav835Z1jmhZQh6TsdWUxxw5HM-bd-h2_xpX72tU"
        }
      },
      "typeVersion": 4.5,
      "notesInBoxView": false
    },
    {
      "id": "0deecdab-6073-4c86-ab73-cf3d2258bc47",
      "name": "Read All Comment IDs",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        384,
        -1792
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 582433129
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Olmrav835Z1jmhZQh6TsdWUxxw5HM-bd-h2_xpX72tU"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "c9daa11a-0d2e-48d1-8a9c-6ae5418b0868",
      "name": "Compile Logged IDs",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        -1792
      ],
      "parameters": {
        "jsCode": "const ids = $input.all().map(item => String(item.json.comment_id));\nreturn [{ json: { ids } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "367e4e5f-ed18-4633-b56f-6aa4afbbf028",
      "name": "Wait 3 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        560,
        -1520
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "28921c79-ac76-482d-b748-91c39ebd98f3",
      "name": "When Every 3 Min",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        208,
        -800
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 3
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "b87546c7-be89-4d47-9eeb-805adb3a94f6",
      "name": "Fetch Telegram Updates",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        992,
        -896
      ],
      "parameters": {
        "url": "https://api.telegram.org/botYOUR_BOT_TOKEN/getUpdates",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "offset",
              "value": "={{$json.offset}}"
            },
            {
              "name": "timeout",
              "value": "0"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "a5233911-f38d-4aae-8177-faa16f05d6b2",
      "name": "Split Telegram Updates",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1440,
        -896
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "result"
      },
      "typeVersion": 1
    },
    {
      "id": "cfd3fa1a-208d-47f3-af2b-3d22a120b73c",
      "name": "Retrieve Stored Offset",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        -896
      ],
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nreturn [{ json: { offset: staticData.telegramOffset || 0 } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d374a5d7-f589-499d-9b67-8964c0a61094",
      "name": "Store New Offset",
      "type": "n8n-nodes-base.code",
      "position": [
        1216,
        -896
      ],
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst response = $input.first().json;\nconst updates = response.result || [];\nif (updates.length > 0) {\n  staticData.telegramOffset = Math.max(...updates.map(u => u.update_id)) + 1;\n}\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "42bb894a-74cf-4c5b-8968-1d6cc8aa68f0",
      "name": "Read Pending Rows",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        416,
        -704
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "pending_review",
              "lookupColumn": "status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 582433129
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Olmrav835Z1jmhZQh6TsdWUxxw5HM-bd-h2_xpX72tU"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "95a89e4c-af6f-4f06-885f-984d40ec1e61",
      "name": "Find Matching Approval",
      "type": "n8n-nodes-base.code",
      "position": [
        2096,
        -880
      ],
      "parameters": {
        "jsCode": "const pendingRows = $('Read Pending Rows').all().map(item => item.json);\nconst replyId = String($json.reply_to_message_id);\nconst match = pendingRows.find(row => String(row.telegram_message_id) === replyId);\nif (!match) return []; // nothing pending matches this reply \u2014 stop quietly\nreturn [{ json: { ...$json, ...match } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "4f44b998-c2cf-4aef-9de2-1f96503d0878",
      "name": "Wait 4 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        416,
        -896
      ],
      "parameters": {
        "amount": 4
      },
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "1c72fc6b-66fb-442a-8d23-d2fae3fac5cc",
  "connections": {
    "Post AI Reply": {
      "main": [
        [
          {
            "node": "Set Telegram & Sheets Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3 Seconds": {
      "main": [
        [
          {
            "node": "Fetch Instagram Media",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 4 Seconds": {
      "main": [
        [
          {
            "node": "Retrieve Stored Offset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Media Data": {
      "main": [
        [
          {
            "node": "Fetch Media Comments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store New Offset": {
      "main": [
        [
          {
            "node": "Split Telegram Updates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Every 3 Min": {
      "main": [
        [
          {
            "node": "Read Pending Rows",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait 4 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Comment Is New": {
      "main": [
        [
          {
            "node": "Post AI Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip Duplicate Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Approval": {
      "main": [
        [
          {
            "node": "Publish Reply on Instagram",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Rejected in Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip Non-match",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Media Context": {
      "main": [
        [
          {
            "node": "Split Comment Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Every 10 Min": {
      "main": [
        [
          {
            "node": "Read All Comment IDs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait 3 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Comment Items": {
      "main": [
        [
          {
            "node": "Exclude Self Comments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Media Comments": {
      "main": [
        [
          {
            "node": "Set Media Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read All Comment IDs": {
      "main": [
        [
          {
            "node": "Compile Logged IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exclude Self Comments": {
      "main": [
        [
          {
            "node": "If Comment Is New",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Instagram Media": {
      "main": [
        [
          {
            "node": "Split Media Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Reply Information": {
      "main": [
        [
          {
            "node": "Find Matching Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Reply In Message": {
      "main": [
        [
          {
            "node": "Set Reply Information",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip Non-reply Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Telegram Updates": {
      "main": [
        [
          {
            "node": "Store New Offset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Matching Approval": {
      "main": [
        [
          {
            "node": "Route by Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Stored Offset": {
      "main": [
        [
          {
            "node": "Fetch Telegram Updates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Telegram Updates": {
      "main": [
        [
          {
            "node": "Check Reply In Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Reply on Instagram": {
      "main": [
        [
          {
            "node": "Mark Approved in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Telegram & Sheets Data": {
      "main": [
        [
          {
            "node": "Send Telegram Approval Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Telegram Approval Request": {
      "main": [
        [
          {
            "node": "Append Pending Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}