AutomationFlowsAI & RAG › Monitor Legal Policy Changes with Google Sheets & GPT-4o

Monitor Legal Policy Changes with Google Sheets & GPT-4o

Original n8n title: Monitor Legal Policy Changes with Google Sheets, Gmail and Gpt-4o

ByAlejandro Alfonso @alejandro02 on n8n.io

Automatically monitors Terms of Service, Privacy Policy, and other legal pages for changes. When content changes are detected, GPT-4o analyzes the old vs new text and emails you a plain-English summary with an impact rating. Every day at 8 AM, the workflow reads your list of…

Cron / scheduled trigger★★★★☆ complexityAI-powered19 nodesGoogle SheetsHTTP RequestChain LlmOpenAI ChatGmail
AI & RAG Trigger: Cron / scheduled Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #14379 — we link there as the canonical source.

This workflow follows the Chainllm → Gmail 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
{
  "id": "97fJO1imnmJICW28",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Terms of Service Change Watcher with AI Summaries",
  "tags": [],
  "nodes": [
    {
      "id": "d1a1b1c1-0001-4000-8000-000000000001",
      "name": "Daily Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        112,
        480
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "d1a1b1c1-0002-4000-8000-000000000002",
      "name": "Get Pages to Monitor",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        336,
        480
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Pages"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d1a1b1c1-0003-4000-8000-000000000003",
      "name": "Fetch Page",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        544,
        480
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (compatible; TOSWatcher/1.0)"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d1a1b1c1-0004-4000-8000-000000000004",
      "name": "Extract & Compare",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Get HTTP response\nconst resp = $input.item.json;\nconst pageData = $('Get Pages to Monitor').item.json;\nconst checkedAt = new Date().toISOString().split('T')[0];\n\n// Detect HTTP errors\nif (resp.error || resp.statusCode >= 400 || resp.status >= 400) {\n  return {\n    url: pageData.url,\n    page_name: pageData.page_name,\n    new_content: '', old_content: '',\n    old_content_for_ai: '', new_content_for_ai: '',\n    changed: false, is_first_run: false,\n    error: 'HTTP error: ' + (resp.error?.message || resp.statusCode || resp.status || 'unknown'),\n    checked_at: checkedAt\n  };\n}\n\n// Get response body\nlet html = '';\nif (typeof resp.data === 'string') html = resp.data;\nelse if (typeof resp.body === 'string') html = resp.body;\nelse if (typeof resp === 'string') html = resp;\nelse html = JSON.stringify(resp);\n\n// Check for Cloudflare/bot challenges\nif (html.includes('Enable JavaScript and cookies') || html.includes('cf-challenge') || html.includes('_cf_chl')) {\n  return {\n    url: pageData.url,\n    page_name: pageData.page_name,\n    new_content: '', old_content: '',\n    old_content_for_ai: '', new_content_for_ai: '',\n    changed: false, is_first_run: false,\n    error: 'Page is behind Cloudflare bot protection - use a different URL',\n    checked_at: checkedAt\n  };\n}\n\n// Check for empty/tiny responses\nif (!html || html.length < 200) {\n  return {\n    url: pageData.url,\n    page_name: pageData.page_name,\n    new_content: '', old_content: '',\n    old_content_for_ai: '', new_content_for_ai: '',\n    changed: false, is_first_run: false,\n    error: 'Page returned empty or very short content',\n    checked_at: checkedAt\n  };\n}\n\n// Strip HTML tags to get plain text\nlet text = html\n  .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n  .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n  .replace(/<[^>]+>/g, ' ')\n  .replace(/&nbsp;/gi, ' ')\n  .replace(/&amp;/gi, '&')\n  .replace(/&lt;/gi, '<')\n  .replace(/&gt;/gi, '>')\n  .replace(/&#\\d+;/gi, '')\n  .replace(/\\s+/g, ' ')\n  .trim()\n  .substring(0, 40000);\n\n// Compare with previously stored content\nconst oldContent = (pageData.last_content || '').trim();\nconst isFirstRun = oldContent === '';\nconst changed = !isFirstRun && oldContent !== text;\n\n// Build smart AI context: find WHERE the texts differ\nlet oldForAi = oldContent.substring(0, 10000);\nlet newForAi = text.substring(0, 10000);\n\nif (changed && oldContent.length > 0) {\n  // Find first point of difference\n  let diffStart = 0;\n  const minLen = Math.min(oldContent.length, text.length);\n  for (let i = 0; i < minLen; i++) {\n    if (oldContent[i] !== text[i]) {\n      diffStart = i;\n      break;\n    }\n    if (i === minLen - 1) diffStart = minLen;\n  }\n\n  // Take context: 500 chars before diff, then 4500 chars after\n  const contextBefore = Math.max(0, diffStart - 500);\n  const prefix = contextBefore > 0 ? '...[IDENTICAL CONTENT SKIPPED]... ' : '';\n\n  const oldDiffSection = prefix + oldContent.substring(contextBefore, contextBefore + 5000);\n  const newDiffSection = prefix + text.substring(contextBefore, contextBefore + 5000);\n\n  // Also grab the tail end of both texts (last 3000 chars)\n  const oldTail = oldContent.length > 5000 ? '\\n\\n...[SKIPPING TO END]...\\n' + oldContent.substring(oldContent.length - 3000) : '';\n  const newTail = text.length > 5000 ? '\\n\\n...[SKIPPING TO END]...\\n' + text.substring(text.length - 3000) : '';\n\n  oldForAi = (oldDiffSection + oldTail).substring(0, 12000);\n  newForAi = (newDiffSection + newTail).substring(0, 12000);\n\n  // Add length comparison as context\n  oldForAi = '[Total length: ' + oldContent.length + ' chars]\\n' + oldForAi;\n  newForAi = '[Total length: ' + text.length + ' chars]\\n' + newForAi;\n}\n\nreturn {\n  url: pageData.url,\n  page_name: pageData.page_name,\n  new_content: text,\n  old_content: oldContent,\n  old_content_for_ai: oldForAi,\n  new_content_for_ai: newForAi,\n  changed: changed,\n  is_first_run: isFirstRun,\n  checked_at: checkedAt\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "d1a1b1c1-0005-4000-8000-000000000005",
      "name": "Content Changed?",
      "type": "n8n-nodes-base.if",
      "position": [
        992,
        480
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-changed",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.changed }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d1a1b1c1-0006-4000-8000-000000000006",
      "name": "Summarize Changes",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1216,
        272
      ],
      "parameters": {
        "text": "=You are a legal document analyst. You MUST compare the two text versions below word-by-word and identify ONLY real, verifiable differences. Do NOT guess or generalize. Every change you list must quote the actual text that was added, removed, or modified.\n\nPage: {{ $json.page_name }} ({{ $json.url }})\n\n--- OLD VERSION ---\n{{ $json.old_content_for_ai }}\n\n--- NEW VERSION ---\n{{ $json.new_content_for_ai }}\n\nRules:\n- ONLY report changes you can verify by comparing the two texts above\n- Quote the specific text that changed (use \"was: ...\" and \"now: ...\" format)\n- If large sections were added or removed, summarize what was added/removed with a brief quote\n- If you cannot find concrete differences, say so honestly\n- NEVER fabricate or assume changes that are not visible in the text\n\nRespond in this format:\n\n**Overview:** One sentence on what changed.\n\n**Changes:**\n- [Quote the specific old text \u2192 new text for each change]\n\n**Impact Level:** LOW (cosmetic/formatting), MEDIUM (policy clarification), or HIGH (new restrictions, rights changes, data handling changes)\n\n**What This Means For Users:** Brief practical impact in 1-2 sentences.",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "d1a1b1c1-0007-4000-8000-000000000007",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1328,
        480
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "gpt-4o"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "d1a1b1c1-0008-4000-8000-000000000008",
      "name": "Build Email Body",
      "type": "n8n-nodes-base.code",
      "position": [
        1520,
        272
      ],
      "parameters": {
        "jsCode": "// Get AI summaries and build email bodies\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const summary = item.json.text || item.json.output || 'No summary available';\n  const p = $('Extract & Compare').item.json;\n\n  const body = '<h2>TOS Change Detected</h2>' +\n    '<p><strong>Page:</strong> ' + p.page_name + '</p>' +\n    '<p><strong>URL:</strong> <a href=\"' + p.url + '\">' + p.url + '</a></p>' +\n    '<p><strong>Detected:</strong> ' + p.checked_at + '</p>' +\n    '<hr><h3>AI Summary of Changes</h3>' +\n    '<div>' + summary.replace(/\\n/g, '<br>') + '</div>' +\n    '<hr><p style=\"color:#666;font-size:12px;\">Generated by your TOS Change Watcher workflow in n8n.</p>';\n\n  results.push({\n    json: {\n      email_subject: 'TOS Change Alert: ' + p.page_name,\n      email_body: body,\n      url: p.url,\n      page_name: p.page_name,\n      summary: summary,\n      checked_at: p.checked_at,\n      new_content: p.new_content\n    }\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "d1a1b1c1-0009-4000-8000-000000000009",
      "name": "Send Change Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1744,
        272
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.email_body }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $json.email_subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d1a1b1c1-0010-4000-8000-000000000010",
      "name": "Log Change",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1968,
        272
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $('Build Email Body').item.json.url }}",
            "date": "={{ $('Build Email Body').item.json.checked_at }}",
            "summary": "={{ $('Build Email Body').item.json.summary }}",
            "page_name": "={{ $('Build Email Body').item.json.page_name }}"
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "page_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "page_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Change Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d1a1b1c1-0011-4000-8000-000000000011",
      "name": "Update Page Record",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2192,
        272
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $('Build Email Body').item.json.url }}",
            "last_checked": "={{ $('Build Email Body').item.json.checked_at }}",
            "last_content": "={{ $('Build Email Body').item.json.new_content }}"
          },
          "schema": [
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "page_name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "page_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_content",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_content",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "last_checked",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_checked",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "url"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Pages"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d1a1b1c1-0012-4000-8000-000000000012",
      "name": "Update Last Checked",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1312,
        704
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $json.url }}",
            "last_checked": "={{ $json.checked_at }}",
            "last_content": "={{ $json.new_content }}"
          },
          "schema": [
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "page_name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "page_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_content",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_content",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "last_checked",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_checked",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "url"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Pages"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ff8245b2-e93e-4e59-a788-cdbd45168947",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -496,
        112
      ],
      "parameters": {
        "width": 480,
        "height": 576,
        "content": "## Terms of Service Change Watcher with AI Summaries\n\n### How it works\n\n1. Schedules a daily check using Daily Check. 2. Retrieves URLs from a Google Sheets workbook. 3. Fetches the specified pages and compares content. 4. Uses an AI model to summarize changes if detected. 5. Sends a change alert email and logs the change.\n\n### Setup steps\n\n- [ ] Set up Google Sheets credentials for retrieving and storing page data\n- [ ] Configure the OpenAI Chat Model for generating AI summaries\n- [ ] Set up Gmail credentials to send email alerts\n\n### Customization\n\nTo monitor different URLs, update the Google Sheets file with new entries."
      },
      "typeVersion": 1
    },
    {
      "id": "569e6c4b-1e32-4115-bba9-a44c2b617e55",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        112
      ],
      "parameters": {
        "color": 7,
        "height": 320,
        "content": "## Daily scheduling\n\nInitiates the workflow on a daily schedule to start the monitoring process."
      },
      "typeVersion": 1
    },
    {
      "id": "df09ebc6-6e09-485f-9e52-de324eb3ad6e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 304,
        "content": "## Fetch pages for monitoring\n\nRetrieves list of pages to monitor from Google Sheets and fetches each page's content."
      },
      "typeVersion": 1
    },
    {
      "id": "b41ea4ec-843a-45e2-8cee-1dd752b63b83",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 304,
        "content": "## Content comparison\n\nCompares the fetched content with the stored version to detect changes."
      },
      "typeVersion": 1
    },
    {
      "id": "e8a861fa-fe1a-4cd2-9bda-3cd662a48707",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 512,
        "content": "## AI-driven change summarization\n\nIf changes are detected, uses AI to summarize the differences between the current and previous content."
      },
      "typeVersion": 1
    },
    {
      "id": "2d1c015b-5155-4bc6-abb1-8cd12acec10d",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1696,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 272,
        "content": "## Email alert and logging\n\nBuilds the email content, sends alerts via Gmail, and logs the change in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "2ab6260a-1077-4802-af7e-da93e445bde5",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        784
      ],
      "parameters": {
        "color": 7,
        "height": 384,
        "content": "## Update monitoring records\n\nUpdates the Google Sheets record to reflect the latest check time, whether changes were detected or not."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "12c7e745-a7ce-4547-8c9a-0bcb3a4eb7a7",
  "connections": {
    "Fetch Page": {
      "main": [
        [
          {
            "node": "Extract & Compare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Change": {
      "main": [
        [
          {
            "node": "Update Page Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Check": {
      "main": [
        [
          {
            "node": "Get Pages to Monitor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Email Body": {
      "main": [
        [
          {
            "node": "Send Change Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Content Changed?": {
      "main": [
        [
          {
            "node": "Summarize Changes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update Last Checked",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract & Compare": {
      "main": [
        [
          {
            "node": "Content Changed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Summarize Changes",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Send Change Alert": {
      "main": [
        [
          {
            "node": "Log Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Summarize Changes": {
      "main": [
        [
          {
            "node": "Build Email Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pages to Monitor": {
      "main": [
        [
          {
            "node": "Fetch Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

Automatically monitors Terms of Service, Privacy Policy, and other legal pages for changes. When content changes are detected, GPT-4o analyzes the old vs new text and emails you a plain-English summary with an impact rating. Every day at 8 AM, the workflow reads your list of…

Source: https://n8n.io/workflows/14379/ — 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

This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p

OpenAI Chat, Output Parser Item List, HTTP Request +10
AI & RAG

[](https://youtu.be/sKJAypXDTLA)

Chain Llm, Agent, Execute Workflow Trigger +6
AI & RAG

This n8n template shows you how to turn outbound sales into a fully automated machine: scrape verified leads, research them with AI, and fire off personalized cold emails while you sleep.

OpenAI Chat, HTTP Request, Google Sheets +5
AI & RAG

Linkedin Automation. Uses httpRequest, lmChatOpenAi, googleSheets, chainLlm. Scheduled trigger; 18 nodes.

HTTP Request, OpenAI Chat, Google Sheets +3
AI & RAG

This workflow automates the process of creating, approving, and optionally posting LinkedIn content from a Google Sheet. Here's a high-level overview: Scheduled Trigger: Runs automatically based on yo

HTTP Request, OpenAI Chat, Google Sheets +3