AutomationFlowsAI & RAG › Linkedin Growth & Intelligence Agent

Linkedin Growth & Intelligence Agent

LinkedIn Growth & Intelligence Agent. Uses telegram, postgres, executeWorkflowTrigger, @brightdata/n8n-nodes-brightdata. Event-driven trigger; 46 nodes.

Event trigger★★★★★ complexityAI-powered46 nodesTelegramPostgresExecute Workflow Trigger@Brightdata/N8N Nodes BrightdataAgentOutput Parser StructuredOpenAI ChatTelegram Trigger
AI & RAG Trigger: Event Nodes: 46 Complexity: ★★★★★ AI nodes: yes Added:
Linkedin Growth & Intelligence Agent — n8n workflow card showing Telegram, Postgres, Execute Workflow Trigger integration

This workflow follows the Agent → Execute Workflow Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "LinkedIn Growth & Intelligence Agent",
  "nodes": [
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83d\udc4b *Hey! Welcome to LinkedIn Growth & Intelligence Agent*\n\n\ud83c\udfaf *What I do*  \nI track public LinkedIn company data in real time and turn it into actionable insights for:  \n\u2022 \ud83d\udd0e Smart B2B prospecting (opportunity scoring & next best actions)  \n\u2022 \ud83d\udcca Competitive intelligence (hiring spikes, leadership changes, company pivots)  \n\u2022 \ud83d\udca1 Content recommendations (top engaging posts & ideas you can reuse)  \n\n\u2728 *Commands*  \n\u2022 /prospect \u2192 analyze a LinkedIn company URL and score opportunities  \n\u2022 /watch \u2192 start monitoring competitors and get alerts on key changes  \n\u2022 /content \u2192 get weekly trending content + new post ideas  \n\u2022 /clear \u2192 reset your current selection  \n\u2022 /help \u2192 show usage tips  \n\n\u2139\ufe0f *Good to know*  \nOnly public LinkedIn data is processed. Insights are delivered straight to Slack/Telegram or your CRM.\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1248,
        640
      ],
      "id": "e1543155-4cd0-4476-b53d-816b1d23bb35",
      "name": "/start",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83e\udd14 *How to use LinkedIn Growth & Intelligence Agent*\n\n\ud83d\udd0e *Step 1 \u2014 Send me a LinkedIn company URL*  \nJust type or paste one a public LinkedIn company profiles, like:  \nhttps://www.linkedin.com/company/openai/  \nhttps://www.linkedin.com/company/nvidia/  \n\n\ud83d\udee0\ufe0f *Step 2 \u2014 Commands*  \n\u2022 /prospect \u2192 analyze the company you sent and score opportunities  \n\u2022 /content \u2192 get trending posts & ideas for your own LinkedIn content  \n\u2022 /clear \u2192 reset your current company list  \n\u2022 /help \u2192 show this help message again  \n\n\ud83d\udcca *What you\u2019ll get*  \nFor each company, I\u2019ll provide:  \n- Size, industry & followers  \n- Hiring activity & growth signals  \n- Engagement trends on recent posts  \n- A *business opportunity score* + recommended next actions  \n\n\u2139\ufe0f *Pro tip*  \nOnly public LinkedIn data is used. Perfect for *B2B prospecting, competitive intelligence, and content strategy*.\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1472,
        1168
      ],
      "id": "616e5d58-0acc-4ffd-b700-5dc93bde4ebc",
      "name": "/help",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83e\uddf9 *Selection cleared* \n\nSend me new LinkedIn company or profile URL, then use:  \n\n\u2022 /prospect \u2192 analyze & score   \n\u2022 /content \u2192 get content ideas\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1248,
        832
      ],
      "id": "ba68206f-6480-4d91-a315-6e81d350fc40",
      "name": "/clear",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "765ed8db-7152-4c40-87b8-e0b9cfd3e80f",
              "name": "chat_id",
              "value": "={{ $json.message.chat.id }}",
              "type": "string"
            },
            {
              "id": "6afe501f-5edc-4c26-b482-f62748f2b245",
              "name": "text",
              "value": "={{ $json.message.text }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -2592,
        1072
      ],
      "id": "6618de56-7422-4a27-95df-7568eab561f5",
      "name": "Prep - Telegram"
    },
    {
      "parameters": {
        "operation": "upsert",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "linkedin_selection",
          "mode": "list",
          "cachedResultName": "linkedin_selection"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "chat_id": "={{ $json.chat_id }}",
            "urls": "={{ $json.urls }}"
          },
          "matchingColumns": [
            "chat_id"
          ],
          "schema": [
            {
              "id": "chat_id",
              "displayName": "chat_id",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "urls",
              "displayName": "urls",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "array",
              "canBeUsedToMatch": false
            },
            {
              "id": "updated_at",
              "displayName": "updated_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        -1920,
        1168
      ],
      "id": "7f59afeb-7a8f-4446-9500-70f9d1347b4b",
      "name": "Upsert LinkedIn URLs",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "deleteTable",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "linkedin_selection",
          "mode": "list",
          "cachedResultName": "linkedin_selection"
        },
        "deleteCommand": "delete",
        "where": {
          "values": [
            {
              "column": "chat_id",
              "value": "={{ $('Prep - Telegram').item.json.chat_id }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        -1472,
        832
      ],
      "id": "3f1ef9ab-a8af-415e-99d1-c3dd88de751d",
      "name": "Delete stored chat",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "/start",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "a26ffeca-a4f9-43ef-83c7-0c6c0adaa733"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "start"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "9f7c3717-89b2-4da6-8f9b-6893921eaea2",
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "/clear",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "clear"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "64c4d192-61dc-4886-b8e0-16628b3ecada",
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "/help",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "help"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "5ae6aa3e-2b59-4fd5-8688-abc31697bd5c",
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "default"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        -1696,
        1040
      ],
      "id": "1dd96b17-8160-4c87-9b50-031d3aeadcc7",
      "name": "Check for global commands"
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83d\udc4b *Welcome back!*  \n\nI found *{{ $json.urls.length }} LinkedIn URL(s)* already saved for you.  \n\nYou can now:  \n\u2022 `/prospect` \u2192 analyze and score them  \n\u2022 `/watch` \u2192 start monitoring for changes \n\u2022 `/content` \u2192 get top posts & new ideas  \n\nOr send new LinkedIn URLs to update your selection.",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1248,
        448
      ],
      "id": "6dc20f46-b87c-4e70-b051-d80e9d5356c4",
      "name": "welcome-back",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "34043973-4b4f-4b67-9989-0dd5c3af105a",
              "leftValue": "={{ $json.urls.urls }}",
              "rightValue": "",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -1472,
        448
      ],
      "id": "2a9b258e-375c-469c-a085-21f821053396",
      "name": "User has set URLS"
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=Please send public LinkedIn company URL first, then /prospect.",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1248,
        1456
      ],
      "id": "5931c1f8-00a1-44bc-9225-bf3f7b444d6d",
      "name": "No URLs set by user",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Code \u00e0 utiliser dans un n\u0153ud Code n8n\nconst inputData = $('Has URLs Stored').all();\n\nconst result = inputData.map(item => {\n  const data = item.json;\n  \n  // Transformer le tableau d'URLs en tableau d'objets\n  const urlObjects = data.urls.map(url => ({\n    url: url\n  }));\n  \n  return {\n    json: {\n      urls: urlObjects\n    }\n  };\n});\n\nreturn result;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1024,
        1216
      ],
      "id": "1c0f5348-d845-400a-9504-dc36bfbafa69",
      "name": "Code"
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83d\udd0e Analyzing {{$json.urls.length}} LinkedIn URL(s)\u2026 I\u2019ll send results here.",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        -1248,
        1216
      ],
      "id": "2a9db65c-526a-4931-b94f-29df84a29c1a",
      "name": "Send Analyzing",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "b935ae85-a3d7-4cfb-a545-bbc92bee3cb4",
              "leftValue": "={{ $json.urls }}",
              "rightValue": "",
              "operator": {
                "type": "array",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -2144,
        1072
      ],
      "id": "986828da-f58e-424a-bc7e-5ef0727baabd",
      "name": "If"
    },
    {
      "parameters": {
        "operation": "select",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "linkedin_selection",
          "mode": "list",
          "cachedResultName": "linkedin_selection"
        },
        "limit": 1,
        "where": {
          "values": [
            {
              "column": "chat_id",
              "value": "={{ $json.chat_id }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        -1920,
        976
      ],
      "id": "0f41e7e3-4de2-4938-8ec6-5b424c0b679e",
      "name": "Select rows from a table",
      "alwaysOutputData": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "snapshot_id"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        -2816,
        2160
      ],
      "id": "956eadf4-cb21-4b8b-a294-89eafeb60e7e",
      "name": "BrightData Scraper Sub-Workflow"
    },
    {
      "parameters": {
        "resource": "webScrapper",
        "operation": "triggerCollectionByUrl",
        "dataset_id": {
          "__rl": true,
          "value": "gd_l1vikfnt1wgvvqz95w",
          "mode": "list",
          "cachedResultName": "LinkedIn company information"
        },
        "urls": "={{ $json.urls.toJsonString() }}",
        "requestOptions": {}
      },
      "type": "@brightdata/n8n-nodes-brightdata.brightData",
      "typeVersion": 1,
      "position": [
        -800,
        1216
      ],
      "id": "fc279645-5c1f-4651-b04c-0eab1e09c97a",
      "name": "Initiate batch extraction for Companies",
      "credentials": {
        "brightdataApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "yNGc5OuaemnrXMaQ",
          "mode": "list",
          "cachedResultName": "LinkedIn Growth & Intelligence Agent"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "snapshot_id",
              "displayName": "snapshot_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "mode": "each",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        -576,
        1216
      ],
      "id": "a20d7eba-47e5-4c40-90b1-c4f39d20df2d",
      "name": "Execute Bright Data Sub workflow Loop for Companies"
    },
    {
      "parameters": {
        "options": {
          "reset": true
        }
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -2592,
        2160
      ],
      "id": "c02bb61b-82e4-4c23-bf1c-86f8231d8f17",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "resource": "webScrapper",
        "operation": "monitorProgressSnapshot",
        "snapshot_id": "={{ $json.snapshot_id }}",
        "requestOptions": {}
      },
      "type": "@brightdata/n8n-nodes-brightdata.brightData",
      "typeVersion": 1,
      "position": [
        -2368,
        2096
      ],
      "id": "a27175df-9ca6-43aa-9d28-d861818847b2",
      "name": "Check the status of a batch extraction",
      "credentials": {
        "brightdataApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        -2144,
        2096
      ],
      "id": "cc2cfcee-f81e-4f15-83b1-9bcd53ed3883",
      "name": "Wait 5 seconds"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "aaf6fec4-cbe7-4fa3-94c7-d169dcb83ac1",
              "leftValue": "={{ $('Check the status of a batch extraction').item.json.status }}",
              "rightValue": "ready",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -1920,
        2096
      ],
      "id": "49277942-0704-4638-872d-683fb92639d5",
      "name": "Check if Batch ready"
    },
    {
      "parameters": {
        "resource": "webScrapper",
        "operation": "downloadSnapshot",
        "snapshot_id": "={{ $('Loop Over Items').item.json.snapshot_id }}",
        "requestOptions": {}
      },
      "type": "@brightdata/n8n-nodes-brightdata.brightData",
      "typeVersion": 1,
      "position": [
        -1696,
        2048
      ],
      "id": "3e583d1f-1d7d-4685-b90b-2bfae047cdbc",
      "name": "Download the snapshot content",
      "credentials": {
        "brightdataApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "name": "Check Snapshot Again for Success",
      "typeVersion": 1,
      "position": [
        -1696,
        2256
      ],
      "id": "d445bf9d-efed-4d25-b053-411f10185416"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const cleanInt = (s) =>\n  s == null ? null : (Number(String(s).replace(/[^0-9]/g, \"\")) || 0);\n\nconst asStr = (v, max = 4000) =>\n  (v == null ? \"\" : String(v)).slice(0, max);\n\nconst source = $json;\nconst p0 = source || {};\n\nconst followers = cleanInt(p0.followers);\nconst sizeRange = p0.company_size || p0.size_range || null;\n\n// Map des posts depuis \"updates\" Bright Data\nconst posts = Array.isArray(p0.updates)\n  ? p0.updates.map(u => ({\n      id: u.post_id ?? null,\n      date: u.date ?? null,\n      text: asStr(u.text, 1500),\n      likes: cleanInt(u.likes_count),\n      comments: cleanInt(u.comments_count),\n      post_url: u.post_url ?? null\n    }))\n  : [];\n\nlet jobsOpenProxy = null;\nif (typeof p0.additional_information === \"string\") {\n  const m =\n    p0.additional_information.match(/(\\d+)\\s+open jobs/i) ||\n    p0.additional_information.match(/\\((\\d+)\\s+open jobs\\)/i);\n  jobsOpenProxy = m ? Number(m[1]) : null;\n}\n\nreturn {\n  sourceUrl: p0.input?.url || p0.url,\n  name: p0.name,\n  linkedin_url: p0.url,\n  industry: p0.industries || p0.specialties || null,\n  size_range: sizeRange,\n  employee_count_est: cleanInt(p0.employees_in_linkedin),\n  followers,\n  description: asStr(p0.description),\n  last_posts: posts,\n  jobs_open_proxy: jobsOpenProxy,\n  executives: p0.employees || [],\n  metrics: {},\n};\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        96,
        896
      ],
      "id": "912a7c77-1955-4799-8b7c-efd579a95f54",
      "name": "Normalizer"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const j = $json;\nconst followers = j.followers || 1;\nconst posts = Array.isArray(j.last_posts) ? j.last_posts : [];\n\nconst now = new Date();\nconst D30 = 1000 * 60 * 60 * 24 * 30;\n\nconst recentPosts = posts.filter(p => {\n  if (!p?.date) return false;\n  const t = Date.parse(p.date);\n  return Number.isFinite(t) && (now - t) <= D30;\n});\n\n// fallback: si aucun post horodat\u00e9 dans 30j, on prend les 10 plus r\u00e9cents\nconst postsForER = recentPosts.length\n  ? recentPosts\n  : posts.slice(0, 10);\n\nconst avgER = postsForER.length\n  ? postsForER.reduce((s, p) => {\n      const l = Number(p.likes || 0);\n      const c = Number(p.comments || 0);\n      const sh = Number(p.shares || 0);\n      return s + (l + c + sh) / followers;\n    }, 0) / postsForER.length\n  : 0;\n\n// Sans la liste des jobs dat\u00e9s 30j, on renvoie 0 par d\u00e9faut\n// (on conserve jobs_open_proxy pour d'autres features/affichage)\nconst hiring30 = 0;\n\nreturn {\n  ...j,\n  metrics: {\n    ...j.metrics,\n    avg_eng_rate_30d: avgER,\n    jobs_last_30d: hiring30,\n  },\n  features: {\n    // Fit taille: favorise 100\u20131000 employ\u00e9s si employee_count_est dispo\n    size_fit: (() => {\n      const x = j.employee_count_est || 0;\n      if (!x) return 0.5;\n      if (x >= 100 && x <= 1000) return 1;\n      return Math.max(0.2, Math.exp(-Math.abs(x - 500) / 500));\n    })(),\n    growth_headcount: 0.5, // \u00e0 am\u00e9liorer avec historique\n    hiring_volume: Math.min(1, (j.jobs_open_proxy || 0) / 20),\n    icp_relevance: 0.6,    // \u00e0 ajuster selon ton ICP/mots-cl\u00e9s\n    engagement_activity: Math.min(1, (postsForER.length / 8) * 0.5 + avgER * 0.5),\n    leadership_change: 0,\n    risk_noise: (j.followers < 500 ? 0.6 : 0.2),\n  }\n};\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        320,
        896
      ],
      "id": "04df0561-34de-4ea1-bb77-71caad7b994b",
      "name": "Metrics"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=You are a B2B sales intelligence assistant.  \nAnalyze the company profile below and return a **strict JSON object**, matching the schema exactly.  \nUse the data provided to generate a factual summary, identify post-related insights, and recommend sales actions.  \nAdapt dynamically to the data (e.g., if no job postings, reflect that accordingly).\n\n---\n\nCompany data:\n- Name: {{$json.name}}\n- Industry: {{$json.industry}}\n- Size: {{$json.employee_count_est}} employees ({{$json.size_range}})\n- Followers: {{$json.followers}}\n- Jobs posted in last 30 days: {{$json.metrics.jobs_last_30d}}\n- Average engagement rate (30 days): {{$json.metrics.avg_eng_rate_30d}}\n- Description: {{$json.description}}\n- Recent posts: {{ JSON.stringify($json.last_posts.slice(0,3)) }}\n\n---\n\nSchema (valid JSON only, no markdown, no comments):\n\n{\n  \"summary\": [\n    \ud83e\udde0 *Industry*: {{$json.industry}}  \n    \ud83d\udc65 *Employees*: {{$json.employee_count_est}} (size range: {{$json.size_range}})  \n    \ud83d\udce3 *Followers*: {{$json.followers}}  \n    \ud83d\udcca *Engagement Rate (30d)*: {{$json.metrics.avg_eng_rate_30d}}\n    \ud83d\udcbc *Jobs (30 d)*: {{$json.metrics.jobs_last_30d}}\n  ],\n  \"post_insights\": [\n    {\n      \"key_themes\": [...],\n      \"summary\": \"...\",\n      \"potential_opportunity\": \"...\"\n    }\n  ],\n  \"next_best_actions\": [\n    {\n      \"action\": \"...\",\n      \"description\": \"...\"\n    },\n    {\n      \"action\": \"...\",\n      \"description\": \"...\"\n    },\n    {\n      \"action\": \"...\",\n      \"description\": \"...\"\n    }\n  ]\n}\n\n---\n\nInstructions:\n- Replace all placeholders with actual values from the input JSON.\n- In the `\"summary\"`, write one sentence about job activity:\n  - If `jobs_last_30d > 0`: mention it as active hiring.\n  - If `jobs_last_30d = 0`: mention absence of job postings and suggest possible internal focus.\n- In the `\"summary\"`, the value for `\"avg_eng_rate_30d\"` must be **rounded to 2 decimal places**.\n- `\"post_insights\"`: summarize themes in recent posts (e.g., product launches, geographic expansion, hiring signals, use cases).\n- `\"next_best_actions\"`: must be concrete and sales-relevant (LinkedIn outreach, email, engagement strategy, etc.).\n- Do not include any explanations, markdown, or formatting. Return JSON only.\n",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "You are a B2B Sales Intelligence Assistant.\n\nYour mission is to analyze raw company profiles (provided as structured JSON input) and return **only a JSON object**, strictly following a predefined schema.\n\n---\n\n\ud83c\udfaf Core task:\n- Extract actionable insights useful for B2B sales or prospecting.\n- Adapt dynamically to the presence or absence of data (e.g., hiring activity, post frequency).\n- Always include: a factual summary, key insights from recent social posts, and 3 high-value sales actions.\n\n---\n\n\ud83e\udde0 Behavior Rules:\n- Never ask questions.\n- Never return markdown, explanations, HTML, or comments.\n- Output **JSON only**. No introductory or closing sentences.\n- If a data field is missing or null, adapt the language accordingly (e.g., \"no recent job postings\").\n- Keep tone professional, concise, and neutral.\n- Output should be ready for use in a CRM, sales dashboard, or automation tool.\n\n---\n\n\ud83d\udcca Output JSON Schema:\nYour output must follow this structure, every time:\n\n1. `\"summary\"`: factual, readable overview based on the input.\n2. `\"post_insights\"`: extract key themes and signals from the latest social posts (launches, growth, partnerships, topics).\n3. `\"next_best_actions\"`: 3 actionable recommendations for sales outreach, tailored to the company's context.\n\n---\n\n\ud83e\udde9 Input Structure:\nEach request will provide:\n- A reminder of your role\n- A structured list of company data fields (name, size, industry, etc.)\n- A JSON schema defining the expected output\n- Instructions for dynamic formatting (e.g., conditional language based on hiring activity)\n\n---\n\n\ud83d\udeab Strict Do-Nots:\n- Never output \u201cHere is the JSON\u201d or similar.\n- Never include free-form explanation.\n- Never include markdown formatting or non-JSON content.\n\n---\n\n\ud83c\udfaf Goal:\nBe ready to integrate into Make.com, Slack, Airtable, Zapier, or a GPT-based assistant.  \nYour output must be 100% clean, reusable, and directly usable by a person or system.\n\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        544,
        800
      ],
      "id": "3fa484ae-1743-4177-b8d0-20fe71165cc3",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Scoring (n8n Function node)\n\n// 1) Pull canonical input from the Metrics node (has features + metrics)\nconst metricsNode = $('Metrics').first();\nif (!metricsNode) {\n  // Hard fail-safe: no Metrics node found\n  return {\n    json: {\n      error: \"Metrics node not found for scoring.\",\n      score: 0,\n      priority: \"C\"\n    }\n  };\n}\n\nconst canonical = metricsNode.json || {};\nconst features = canonical.features || {};\nconst nz = v => (v == null || v === '' ? 0 : Number(v));\n\nconst W = {\n  size_fit: 0.18,\n  growth_headcount: 0.22,\n  hiring_volume: 0.15,\n  icp_relevance: 0.20,\n  engagement_activity: 0.15,\n  leadership_change: 0.05,\n  risk_noise: -0.05\n};\n\n// 2) Compute score 's' from features\nlet s = 0;\ns += W.size_fit * nz(features.size_fit);\ns += W.growth_headcount * nz(features.growth_headcount);\ns += W.hiring_volume * nz(features.hiring_volume);\ns += W.icp_relevance * nz(features.icp_relevance);\ns += W.engagement_activity * nz(features.engagement_activity);\ns += W.leadership_change * nz(features.leadership_change);\ns += W.risk_noise * nz(features.risk_noise);\n\n// 3) Normalize to 0..100, set priority\nconst score = Math.max(0, Math.min(100, Math.round(100 * s)));\nconst priority = score >= 75 ? 'A' : score >= 50 ? 'B' : 'C';\n\n// 4) Get current branch item (likely holds the AI Agent output)\nconst current = $json || {};\nconst aiOutput = current.output || current; // supports either {output:{...}} or the object itself\n\n// 5) Build a clean 'input' payload from Metrics (avoid echoing 'output' if present)\nconst { output: _drop, ...inputPayload } = canonical;\n\n// 6) Return final unified object\nreturn {\n  json: {\n    input: inputPayload,   // original normalized data + metrics + features\n    output: aiOutput,      // AI Agent result\n    score,\n    priority\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        896,
        896
      ],
      "id": "75b19056-8a4f-4aa7-bd74-4c39c7b132f6",
      "name": "Scoring"
    },
    {
      "parameters": {
        "jsCode": "function filterCompanyUrls(chatData) {\n  // Check if input is valid and convert to array if needed\n  if (!chatData) {\n    console.log(\"No input data provided\");\n    return [];\n  }\n  \n  // Convert single object to array\n  let dataArray = Array.isArray(chatData) ? chatData : [chatData];\n  console.log(\"Processing data:\", dataArray);\n  \n  // Helper function to check if a URL is a company URL (more flexible patterns)\n  function isCompanyUrl(url) {\n    return url.includes('/company/');\n  }\n  \n  // Helper function to clean company URLs (remove everything after company name)\n  function cleanCompanyUrl(url) {\n    if (!url.includes('/company/')) return url;\n    \n    // Find the company part and extract just the base company URL\n    const companyMatch = url.match(/https?:\\/\\/[^\\/]+\\/company\\/[^\\/\\?#]+/);\n    return companyMatch ? companyMatch[0] : url;\n  }\n  \n  // Helper function to extract URLs from text\n  function extractUrls(text) {\n    if (typeof text !== 'string') return [];\n    const urlRegex = /https?:\\/\\/[^\\s]+/g;\n    const urls = text.match(urlRegex) || [];\n    console.log(\"Found URLs:\", urls);\n    const companyUrls = urls.filter(isCompanyUrl).map(cleanCompanyUrl);\n    console.log(\"Cleaned company URLs:\", companyUrls);\n    return companyUrls;\n  }\n  \n  // Group data by chat_id and collect company URLs\n  const result = {};\n  \n  dataArray.forEach(item => {\n    const chatId = item.chat_id;\n    const companyUrls = extractUrls(item.text);\n    \n    if (!result[chatId]) {\n      result[chatId] = {\n        chat_id: chatId,\n        urls: []\n      };\n    }\n    \n    // Add company URLs to the existing array\n    result[chatId].urls.push(...companyUrls);\n  });\n  \n  // Convert result object to array\n  return Object.values(result);\n}\n\nreturn filterCompanyUrls($input.first().json);\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2368,
        1072
      ],
      "id": "fd4749a2-9ffd-4d82-b8fe-2b13c5cf6037",
      "name": "Extract URLs"
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"Company Engagement Schema\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"summary\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"post_insights\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"key_themes\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" }\n          },\n          \"summary\": { \"type\": \"string\" },\n          \"potential_opportunity\": { \"type\": \"string\" }\n        },\n        \"required\": [\"key_themes\", \"summary\", \"potential_opportunity\"]\n      }\n    },\n    \"next_best_actions\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"action\": { \"type\": \"string\" },\n          \"description\": { \"type\": \"string\" }\n        },\n        \"required\": [\"action\", \"description\"]\n      }\n    }\n  },\n  \"required\": [\"summary\", \"next_best_actions\"]\n}\n"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        688,
        1024
      ],
      "id": "71069b27-216f-4bc8-8b58-200b42576bf4",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "/prospect",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "8d84603b-6201-4553-b55b-e001c7a3fe9f"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "prospect"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "0bf8c52b-6e4d-4901-91a2-c8ad9e563124",
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "/content",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "content"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "1c5d74e3-1258-4afd-9e6c-563191165768",
                    "leftValue": "={{ $('Prep - Telegram').item.json.text }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "other"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        -352,
        1200
      ],
      "id": "b843904b-0ffe-4c1b-b898-532738411790",
      "name": "Switch"
    },
    {
      "parameters": {
        "jsCode": "const cleanInt = s => s==null ? null : (Number(String(s).replace(/[^0-9]/g,'')) || 0);\nconst asStr = (v, max=1500) => (v==null?'':String(v)).slice(0,max);\n\nconst json = $input.first().json;\n\n// Followers & URL\nconst followers = cleanInt(json.followers) || 0;\nconst F = followers > 0 ? followers : 1;\n\nconst postsRaw = Array.isArray(json.updates) ? json.updates : [];\n\n// Normalizerr by post + ER fallback (likes+comments+shares)/max(1,followers)\nconst posts = postsRaw.map(u => {\n  const likes = cleanInt(u.likes_count ?? u.likes) || 0;\n  const comments = cleanInt(u.comments_count ?? u.comments) || 0;\n\n  const date = u.date || null;\n  const er = (likes + comments) / F;\n\n  return {\n    id: u.post_id ?? u.id ?? null,\n    date,\n    text: asStr(u.text ?? u.text_html?.replace(/<[^>]*>/g,' ') ?? ''),\n    likes, comments,\n    engagement_rate: er,\n    post_url: u.post_url ?? u.url ?? null,\n    title: u.title ?? null,\n  };\n});\n\nreturn [{\n  json: {\n    company: json.name || json.title || 'Company',\n    followers: followers || null,\n    linkedin_url: json.url || json.input?.url || null,\n    posts\n  }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -128,
        1456
      ],
      "id": "3e0bc147-15d7-4430-8f6a-3b3c112554b2",
      "name": "Normalize Posts"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const now = Date.now(), D30 = 1000*60*60*24*30;\nconst data = $json;\n\nconst parseTs = (s) => {\n  const t = Date.parse(s || '');\n  return Number.isFinite(t) ? t : null;\n};\n\n// filter last 30 days ; fallback = keep last 10\nconst recent = (data.posts || []).filter(p => {\n  const t = parseTs(p.date);\n  return t && (now - t) <= D30;\n});\n\nconst candidates = recent.length ? recent : (data.posts || []).slice(0, 10);\n\nfunction keywords(s){\n  return (String(s||'').toLowerCase()\n    .replace(/[^a-z0-9\\s]/g,' ')\n    .split(/\\s+/)\n    .filter(w => w.length >= 4)\n    .slice(0,8));\n}\n\nconst used = new Set();\nconst top_posts = candidates\n  .slice()\n  .sort((a,b) => (b.engagement_rate||0) - (a.engagement_rate||0))\n  .filter(p => {\n    const key = (keywords(p.text).slice(0,2).join('|')) || 'misc';\n    if (used.has(key)) return false;\n    used.add(key);\n    return true;\n  })\n  .slice(0,3);\n\nreturn { json: {\n  ...data,\n  recent_window_days: 30,\n  top_posts,\n  has_posts: !!top_posts.length\n}};\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        96,
        1456
      ],
      "id": "2e3b533d-1baa-4fdd-bcd5-e073d8346ed1",
      "name": "Rank Posts"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Company: {{$json.company}}\nFollowers: {{$json.followers}}\nWindow (days): {{$json.recent_window_days}}\n\nTopPosts (JSON):\n{{ JSON.stringify($json.top_posts) }}\n\nTask:\n1. Extract 3\u20135 short insights about what performs in these posts (themes, formats, angles).\n2. Generate 3\u20135 LinkedIn post ideas inspired by those posts (no copy-paste).\n3. Each idea must include: title, hook, angle, 3 bullets, CTA.\n4. Return valid JSON only, matching this structure:\n\n\nAdd company, recent_window_days and top_posts on output\nIf you cannot extract insights from the posts, write: [\"No insights available.\"]\nIf you cannot generate post ideas, write 3 ideas based on company\u2019s context alone.\n\n",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "You are a B2B LinkedIn content strategist.\n\nYour role:\n- Read the company profile and its top-performing LinkedIn posts.\n- Extract 3\u20135 key content insights.\n- Generate 3\u20135 new LinkedIn post ideas based on what worked, without copying.\n\nEach idea includes:\n- title\n- hook (max 120 chars)\n- angle\n- 3 short bullets\n- CTA (call to action)\n\nTone: expert, concise, realistic for LinkedIn.\n\nIf input is limited, still generate 3 ideas using only company info.\n\n\u26a0\ufe0f Return JSON only (no markdown, no prose). \n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        544,
        1200
      ],
      "id": "dba6068a-fc8f-43fb-b000-f2471e1b8098",
      "name": "AI Ideas Content"
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\u2139\ufe0f No recent public posts found.\nTry widening the window or adding more sources. You can still use /prospect for scoring.\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        608,
        1600
      ],
      "id": "e104f8a7-35d8-4eb0-84a5-457cfd6371a1",
      "name": "Fallback",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"Content Generation Output\",\n  \"type\": \"object\",\n  \"required\": [\"input\", \"insights\", \"post_ideas\"],\n  \"properties\": {\n    \"input\": {\n      \"type\": \"object\",\n      \"required\": [\"company\", \"followers\", \"recent_window_days\", \"top_posts\"],\n      \"properties\": {\n        \"company\": { \"type\": \"string\" },\n        \"followers\": { \"type\": \"number\" },\n        \"recent_window_days\": { \"type\": \"number\" },\n        \"top_posts\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"required\": [\"id\", \"date\", \"text\", \"likes\", \"comments\", \"engagement_rate\", \"post_url\", \"title\"],\n            \"properties\": {\n              \"id\": { \"type\": \"string\" },\n              \"date\": { \"type\": \"string\", \"format\": \"date-time\" },\n              \"text\": { \"type\": \"string\" },\n              \"likes\": { \"type\": \"number\" },\n              \"comments\": { \"type\": \"number\" },\n              \"engagement_rate\": { \"type\": \"number\" },\n              \"post_url\": { \"type\": \"string\", \"format\": \"uri\" },\n              \"title\": { \"type\": \"string\" }\n            }\n          }\n        }\n      }\n    },\n    \"insights\": {\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"items\": { \"type\": \"string\" }\n    },\n    \"post_ideas\": {\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"items\": {\n        \"type\": \"object\",\n        \"required\": [\"title\", \"hook\", \"angle\", \"bullets\", \"cta\"],\n        \"properties\": {\n          \"title\": { \"type\": \"string\" },\n          \"hook\": { \"type\": \"string\", \"maxLength\": 120 },\n          \"angle\": { \"type\": \"string\" },\n          \"bullets\": {\n            \"type\": \"array\",\n            \"minItems\": 3,\n            \"maxItems\": 3,\n            \"items\": { \"type\": \"string\" }\n          },\n          \"cta\": { \"type\": \"string\" }\n        }\n      }\n    }\n  }\n}\n"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        688,
        1424
      ],
      "id": "2c41a141-dd96-4958-ac87-01ae8d08664a",
      "name": "Structured Output Parser1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "ecacd325-3734-4558-bc7f-5ba8c27a2b80",
              "leftValue": "={{ $json.has_posts }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        320,
        1456
      ],
      "id": "65bdbe0b-4283-40a8-b0c2-055b789aaa8a",
      "name": "HasPost"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        560,
        1024
      ],
      "id": "372746e3-8b6e-4ed2-9ca3-26381a204568",
      "name": "OpenAI Chat Prospect",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        560,
        1424
      ],
      "id": "c7470e38-fafc-4ff2-bd45-0631150f0be5",
      "name": "OpenAI Chat Content",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.2,
      "position": [
        -2816,
        1072
      ],
      "id": "913c6534-76aa-42d4-b24c-c506c3b19da8",
      "name": "Telegram Trigger",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83d\udca1 *Content Digest \u2013 {{ $json.output.input.company }}*\n\n\ud83d\uddd3\ufe0f *Top Posts (last {{$json.output.input.recent_window_days}} days)*:\n{{ $json.output.input.top_posts.map((item) => {\n    return `\u2022 ${item.date.slice(0,10)}  ${item.text.slice(0,60)} \u2014 ER ${Number(item.engagement_rate).toFixed(3)}`\n}).join('\\n')}}\n\n\ud83d\udccc *Insights*:\n{{ $json.output.insights.map((item) => (`\u2022 ${item}`)).join('\\n')}}\n\n\n\ud83e\udde0 *Post Ideas*:\n{{ $json.output.post_ideas.map((item, index) => {\n    return `${index + 1} *${item.title}*\n  _Hook_: ${item.hook}\n  _Angle_: ${item.angle}\n  _Structure_:\n${item.bullets.map((item) => (`    \u2022 ${item}`)).join('\\n')}\n  _CTA_: ${item.cta}\n`\n}).join('\\n')}}\n\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        896,
        1296
      ],
      "id": "251a0199-416a-4c9d-85c4-9108ae744b89",
      "name": "Send Content message",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Prep - Telegram').item.json.chat_id }}",
        "text": "=\ud83d\udccc *Company Profile Summary \u2013 {{ $('Normalizer').item.json.name }}*\n\n\u26a0\ufe0f *Priority Score*: *{{$json.priority}}*\n---\n\n{{ $json.output.summary.join('\\n') }}\n---\n\n\ud83c\udfaf *Recommended Next Actions*\n\n1\ufe0f\u20e3 *{{ $json.output.next_best_actions[0].action }}*\n{{ $json.output.next_best_actions[0].description }}\n\n2\ufe0f\u20e3 *{{ $json.output.next_best_actions[1].action }}*\n{{ $json.output.next_best_actions[1].description }}\n\n3\ufe0f\u20e3 *{{ $json.output.next_best_actions[2].action }}*\n{{ $json.output.next_best_actions[2].description }}\n\n\n",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1120,
        896
      ],
      "id": "2ee76108-e2d6-485c-bf5e-5122e537f958",
      "name": "Send Prospect message",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "34043973-4b4f-4b67-9989-0dd5c3af105a",
              "leftValue": "={{ $json.urls }}",
              "rightValue": "",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -1472,
        1360
      ],
      "id": "043366fb-5e2e-4a05-81a9-837b19c2f75a",
      "name": "Has URLs Stored"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DROP TABLE IF EXISTS linkedin_selection;\nCREATE TABLE IF NOT EXISTS linkedin_selection (\n  chat_id TEXT PRIMARY KEY,\n  urls text[],\n  updated_at TIMESTAMPTZ DEFAULT now()\n);",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        -2432,
        1632
      ],
      "id": "d0549907-1157-4a5c-ba75-acf38c710b5d",
      "name": "Initialize database tables",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## \ud83c\udfaf Purpose: Initialize database tables for the Growth Radar bot\n\n- Creates table `linkedin_selection` if it doesn\u2019t exist\n- Stores mapping: { chat_id, urls, last_updated }\n- Ensures session persistence across Telegram messages\n- Run once at workflow start (safe to re-run, idempotent)\n\n\u26a0\ufe0f Important: Only stores *public LinkedIn company URLs*",
        "height": 256,
        "width": 672,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -2928,
        1536
      ],
      "id": "72139119-3bfb-470a-8a25-904e5972b7ea",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## \ud83d\udd04 Purpose: Wait until Bright Data snapshot is ready\n\n- Polls snapshot status every 5s\n- If status != \"ready\" \u2192 loop continues\n- Once ready \u2192 downloads snapshot JSON\n- Ensures we always get complete & valid data\n\n\ud83d\udca1 Could be extended with exponential backoff",
        "height": 528,
        "width": 1472,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -2944,
        1952
      ],
      "id": "39f64c89-8e7c-41b1-b2ee-730474006db3",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## \ud83e\udd16 Purpose: Transform Bright Data results into actionable insights\n\n- Uses Structured Output Parser with enforced JSON schema:\n  {\n    \"summary\": [string],\n    \"post_insights\": [ { \"text\": string, \"engagement_rate\": number } ],\n    \"next_best_actions\": [string]\n  }\n\n- Ensures LLM always returns machine-parseable JSON\n- Adds robustness: downstream nodes (Scoring, Telegram Output) consume clean data\n\n\u26a0\ufe0f Fallback handling: if schema fails, default empty arrays are used",
        "height": 2160,
        "width": 4336
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -2976,
        352
      ],
      "id": "54d807ac-0832-4e0b-af75-2bea2af17f31",
      "name": "Sticky Note2"
    }
  ],
  "connections": {
    "Prep - Telegram": {
      "main": [
        [
          {
            "node": "Extract URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert LinkedIn URLs": {
      "main": [
        [
          {
            "node": "Check for global commands",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete stored chat": {
      "main": [
        [
          {
            "node": "/clear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for global commands": {
      "main": [
        [
          {
            "node": "User has set URLS",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Delete stored chat",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "/help",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Has URLs Stored",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "User has set URLS": {
      "main": [
        [
          {
            "node": "welcome-back",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "/start",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/help": {
      "main": [
        []
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Initiate batch extraction for Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Analyzing": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Select rows from a table",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upsert LinkedIn URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select rows from a table": {
      "main": [
        [
          {
            "node": "Check for global commands",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BrightData Scraper Sub-Workflow": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initiate batch extraction for Companies": {
      "main": [
        [
          {
            "node": "Execute Bright Data Sub workflow Loop for Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Bright Data Sub workflow Loop for Companies": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Check the status of a batch extraction",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check the status of a batch extraction": {
      "main": [
        [
          {
            "node": "Wait 5 seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 5 seconds": {
      "main": [
        [
          {
            "node": "Check if Batch ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Batch ready": {
      "main": [
        [
          {
            "node": "Download the snapshot content",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check Snapshot Again for Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Snapshot Again for Success": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalizer": {
      "main": [
        [
          {
            "node": "Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Metrics": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Scoring",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scoring": {
      "main": [
        [
          {
            "node": "Send Prospect message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract URLs": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "a

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

LinkedIn Growth & Intelligence Agent. Uses telegram, postgres, executeWorkflowTrigger, @brightdata/n8n-nodes-brightdata. Event-driven trigger; 46 nodes.

Source: https://gist.github.com/synapz-fr/c80507e189a5213df021665ad6f32e7c — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Template Carnaval - time instagram. Uses toolWorkflow, lmChatOpenAi, memoryBufferWindow, agent. Event-driven trigger; 56 nodes.

Tool Workflow, OpenAI Chat, Memory Buffer Window +10
AI & RAG

6_Multi-Agent_4vaEvzlaMrgovhNz. Uses postgres, httpRequest, lmChatOpenAi, outputParserStructured. Event-driven trigger; 54 nodes.

Postgres, HTTP Request, OpenAI Chat +4
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Output Parser Structured, Telegram, N8N Nodes Tesseractjs +14
AI & RAG

This intelligent lead generation workflow transforms voice commands or text input into verified prospect lists through automated Apollo.io scraping. The system processes natural language requests, ext

Telegram, OpenAI, OpenAI Chat +7
AI & RAG

This workflow is perfect for:

Telegram Trigger, Tool Workflow, Airtable Tool +7