AutomationFlowsSlack & Telegram › Extract Legal Contract Data & Send Alerts with Vlm Run, Google Workspace & Slack

Extract Legal Contract Data & Send Alerts with Vlm Run, Google Workspace & Slack

ByShahrear @shahrear on n8n.io

This workflow automatically extracts, organizes, and tracks legal contract details from documents uploaded to Google Drive. Using VLM Run’s Execute Agent, it parses key metadata such as contract ID, parties, dates, and terms — then stores, alerts, and schedules reminders through…

Event trigger★★★★☆ complexity14 nodesGoogle Drive TriggerGoogle Drive@Vlm Run/N8N Nodes VlmrunGoogle SheetsSlackGoogle Calendar
Slack & Telegram Trigger: Event Nodes: 14 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Calendar → Google Sheets 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "bdfebade-893c-411c-80c6-0dace07f7dc9",
      "name": "\ud83d\udcc1 Input Processing Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 680,
        "content": "## \ud83d\udcc1 Input Processing\n\n**Monitors & downloads contract files from Google Drive.**\n\n**Process:**\n1. Watches designated Drive folder\n2. Auto-triggers on new uploads\n3. Downloads files for AI processing\n\n**Supported Formats:**\n- Images (JPG, PNG, WEBP)\n- PDF documents\n- Mobile camera uploads\n- Scanned contracts"
      },
      "typeVersion": 1
    },
    {
      "id": "2fca40fa-ac4a-4515-a1e0-295cdcbfc595",
      "name": "Monitor Contract Uploads",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "notes": "Monitors Google Drive folder for new receipt uploads and triggers processing automatically.",
      "position": [
        48,
        480
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
          "cachedResultName": "test_data"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "95acb226-9205-4a21-9a2d-c9792bc81de4",
      "name": "Download  Contract File",
      "type": "n8n-nodes-base.googleDrive",
      "notes": "Downloads receipt files from Google Drive for AI processing.",
      "position": [
        256,
        480
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {
          "binaryPropertyName": "data"
        },
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "61fa2c83-72cd-44b0-a5cd-5fbaeef5dfb1",
      "name": "\ud83e\udd16 AI Extraction Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        0
      ],
      "parameters": {
        "width": 416,
        "height": 680,
        "content": "## \ud83e\udd16 VLM Run Contract Extraction\n\n**Uses VLM Run node to extract structured data from contract images/PDFs.**\n\n**Extracts:**\n- Contract ID\n- Title\n- Parties\n- Effective Date\n- Termination Date\n\n**Features:**\n- Handles poor quality images\n- Various receipt formats\n- OCR text recognition"
      },
      "typeVersion": 1
    },
    {
      "id": "84d28c8a-b33c-4bc3-9489-846c3b412d4a",
      "name": "VLM Run ContractParser",
      "type": "@vlm-run/n8n-nodes-vlmrun.vlmRun",
      "position": [
        560,
        480
      ],
      "parameters": {
        "operation": "executeAgent",
        "agentPrompt": "extract data from the invoice or contract, Extract the key details from this lease contract. I am expecting the output to be in JSON format, with tags, using parameters : contract_id, title, parties (with role), property_address, effective_date, termination_date, rent_amount, security_deposit, payment_terms, governing_law . All the parameters should get values from the pdf of data file from the download contract file. \nNormalize dates to YYYY-MM-DD and amounts as numbers with currency.  \nIf a field is missing, return null.",
        "agentCallbackUrl": "https://playground.attensys.ai/webhook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      },
      "credentials": {
        "vlmRunApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "17996d92-afea-484c-88d3-9b2b673b1f4c",
      "name": "\ud83d\udcca Storage Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## \ud83d\udcca Data Storage\n\n**Structures and stores extracted data in Google Sheets.**\n\n**Features:**\n- Clean, organized format\n- Centralized expense database\n- Auto-appends new entries\n- Analysis-ready data\n\n**Data Fields:**\n- ID\n- Title\n- Parties\n- Effective and Termination Date\n\n**Benefits:**\n- Real-time tracking\n- Easy exports\n- Mobile access"
      },
      "typeVersion": 1
    },
    {
      "id": "70c2c9c5-d950-495f-9e91-5a0b402ef739",
      "name": "Save to Expense Database",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Automatically saves extracted receipt data to Google Sheets for expense tracking.",
      "position": [
        1344,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Title": "={{$node[\"Format Contract Data\"].json[\"Title\"]}}",
            "Parties": "={{$node[\"Format Contract Data\"].json[\"Parties\"]}}",
            "Contract ID": "={{$node[\"Format Contract Data\"].json[\"Contract ID\"]}}",
            "Effective Date": "={{$node[\"Format Contract Data\"].json[\"Effective Date\"]}}",
            "Termination Date": "={{$node[\"Format Contract Data\"].json[\"Termination Date\"]}}"
          },
          "schema": [
            {
              "id": "Contract ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Contract ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Parties",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Parties",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Effective Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Effective Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Termination Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Termination Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Customer"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11_VjMdhv_JN2eSRZiw_t0dIN-yShkn2jlCDwiG8eb14/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1lg0aJKvd7E2pbhumHNjcgxUfEQKvlBs9h1zZbhSeqas",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lg0aJKvd7E2pbhumHNjcgxUfEQKvlBs9h1zZbhSeqas/edit?usp=drivesdk",
          "cachedResultName": "test"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "f752ffb1-d4eb-4d69-919d-2f4d72fb753e",
      "name": "Format Contract Data",
      "type": "n8n-nodes-base.set",
      "notes": "Transforms AI-extracted receipt data into clean, structured format for spreadsheet storage.",
      "position": [
        1136,
        480
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "Contract ID",
              "value": "={{ $json.body.response.contract_id }}"
            },
            {
              "name": "Title",
              "value": "={{ $json.body.response.title }}"
            },
            {
              "name": "Parties",
              "value": "={{ $json.body.parties && $json.body.parties.length ? $json.body.parties.map(p => p.name + \" (\"+ p.role + \")\").join(\"; \") : \"\" }}"
            },
            {
              "name": "Effective Date",
              "value": "={{ $json.body.response.effective_date }}"
            },
            {
              "name": "Termination Date",
              "value": "={{ $json.body.response.termination_date }}"
            }
          ]
        },
        "options": {},
        "keepOnlySet": true
      },
      "typeVersion": 1
    },
    {
      "id": "d04b627c-1b80-4692-91a3-2df61bec0b4d",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1712,
        512
      ],
      "parameters": {
        "text": "=*New Contract Processed* \ud83d\udcc4\n\u2022 Contract ID: {{$node[\"Format Contract Data\"].json[\"Contract ID\"] || \"N/A\"}}\n\u2022 Title: {{$node[\"Format Contract Data\"].json[\"Title\"] || \"N/A\"}}\n\u2022 Parties: {{$node[\"Format Contract Data\"].json[\"Parties\"] || \"N/A\"}}\n\u2022 Effective: {{$node[\"Format Contract Data\"].json[\"Effective Date\"] || \"N/A\"}}\n\u2022 Termination: {{$node[\"Format Contract Data\"].json[\"Termination Date\"] || \"N/A\"}}\n\ud83d\udd17 {{$node[\"Format Contract Data\"].json[\"Drive Link\"] || $node[\"Save to Expense Database\"].json[\"driveLink\"] || \"No drive link available\"}}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C081Z0KL546",
          "cachedResultName": "test"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "955768a3-5fac-4296-a5a3-d307a98b471c",
      "name": "Prepare Calendar Events",
      "type": "n8n-nodes-base.code",
      "position": [
        1616,
        336
      ],
      "parameters": {
        "jsCode": "// n8n Function node code\n// Reads from Format Contract Data node and returns 1..3 items, each has .json with summary, description, start, end (YYYY-MM-DD)\n\nconst fmt = $node[\"Format Contract Data\"].json;\nconst title = fmt[\"Title\"] || \"Untitled Contract\";\nconst cid = fmt[\"Contract ID\"] || \"\";\nconst parties = fmt[\"Parties\"] || \"\";\nconst drive = fmt[\"Drive Link\"] || \"\";\n\nfunction isoDate(d) {\n  // return YYYY-MM-DD\n  return d.toISOString().split('T')[0];\n}\n\nfunction makeAllDayDates(dateStr) {\n  // Accepts YYYY-MM-DD (or other parseable), returns start and end for all-day event.\n  if(!dateStr) return null;\n  const d = new Date(dateStr + \"T00:00:00\");\n  const start = isoDate(d);\n  const endD = new Date(d);\n  endD.setDate(endD.getDate() + 1); // exclusive end for all-day events\n  const end = isoDate(endD);\n  return { start, end };\n}\n\nconst items = [];\n\n// Effective Date event\nconst eff = makeAllDayDates(fmt[\"Effective Date\"]);\nif (eff) {\n  items.push({\n    json: {\n      summary: `${title} \u2014 Effective Date`,\n      description: `Contract ID: ${cid}\\nParties: ${parties}\\nDrive: ${drive}`,\n      start: eff.start,\n      end: eff.end,\n      allDay: true,\n      metaType: \"effective\"\n    }\n  });\n}\n\n// Termination Date event\nconst term = makeAllDayDates(fmt[\"Termination Date\"]);\nif (term) {\n  items.push({\n    json: {\n      summary: `${title} \u2014 Termination Date`,\n      description: `Contract ID: ${cid}\\nParties: ${parties}\\nDrive: ${drive}`,\n      start: term.start,\n      end: term.end,\n      allDay: true,\n      metaType: \"termination\"\n    }\n  });\n\n  // Renewal review reminder 60 days before termination\n  const termDate = new Date(fmt[\"Termination Date\"] + \"T00:00:00\");\n  const reminderDate = new Date(termDate);\n  reminderDate.setDate(reminderDate.getDate() - 60); // change 60 to your preferred days\n  const remStart = isoDate(reminderDate);\n  const remEndD = new Date(reminderDate);\n  remEndD.setDate(remEndD.getDate() + 1);\n  const remEnd = isoDate(remEndD);\n\n  items.push({\n    json: {\n      summary: `${title} \u2014 Renewal Review (Reminder)`,\n      description: `Contract ID: ${cid}\\nTermination Date: ${fmt[\"Termination Date\"]}\\nAction: Review & decide renewal.`,\n      start: remStart,\n      end: remEnd,\n      allDay: true,\n      metaType: \"renewal_reminder\"\n    }\n  });\n}\n\nreturn items;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f3301d1a-5773-4598-ba4e-71019a4966bd",
      "name": "Create an event",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        1808,
        336
      ],
      "parameters": {
        "end": "={{$json[\"end\"]}}",
        "start": "={{$json[\"start\"]}}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        },
        "additionalFields": {
          "allday": "yes",
          "summary": "={{$json[\"summary\"]}}",
          "description": "={{$json[\"description\"]}}"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dd656271-d2a3-4f8a-9df8-1da0596b2734",
      "name": "\ud83d\udcca Storage Documentation1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## \ud83d\udd14 Notifications Added:\n\n1. **Slack** \u2192 Posts contract details & AI-generated summary to #all-n8n-test for team visibility.\n\n2. **Google Calendar** \u2192 Auto-creates all-day events:\n   \u2022 Effective Date\n   \u2022 Termination Date\n   \u2022 Renewal Reminder (30 days before)\n   \u2192 Helps track key contract milestones.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "99fdd61d-c6a9-4e74-989a-e56b47caf2e9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        704
      ],
      "parameters": {
        "color": 5,
        "width": 704,
        "height": 144,
        "content": "## \ud83d\udcdd Set the Callback URL\n\nMake sure to paste the **Production URL** of your n8n Webhook node into the **Callback URL** field in VLM Run. This ensures that the extracted image links are securely and reliably sent back to your live workflow. Do **not** use localhost or development URLs, they won\u2019t be reachable by VLM Run\u2019s servers."
      },
      "typeVersion": 1
    },
    {
      "id": "6d26e945-a724-4e3b-a8ff-c91dd8500f5f",
      "name": "Receive Contract",
      "type": "n8n-nodes-base.webhook",
      "position": [
        784,
        480
      ],
      "parameters": {
        "path": "b905e71d-8ea5-4fc2-a773-b0f92e5398e4",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "Receive Contract": {
      "main": [
        [
          {
            "node": "Format Contract Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Contract Data": {
      "main": [
        [
          {
            "node": "Save to Expense Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download  Contract File": {
      "main": [
        [
          {
            "node": "VLM Run ContractParser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Calendar Events": {
      "main": [
        [
          {
            "node": "Create an event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monitor Contract Uploads": {
      "main": [
        [
          {
            "node": "Download  Contract File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Expense Database": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Calendar Events",
            "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

This workflow automatically extracts, organizes, and tracks legal contract details from documents uploaded to Google Drive. Using VLM Run’s Execute Agent, it parses key metadata such as contract ID, parties, dates, and terms — then stores, alerts, and schedules reminders through…

Source: https://n8n.io/workflows/9328/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

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

Slack & Telegram

Stop missing renewal deadlines and overpaying on auto-renewals. This workflow monitors your contract calendar in Google Sheets, sends progressive Slack notifications with manual research checklists, a

Slack, Error Trigger, Google Sheets
Slack & Telegram

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

@Vlm Run/N8N Nodes Vlmrun, Google Drive Trigger, Google Drive +1
Slack & Telegram

This workflow is a production-ready Meta Ads Webhook dispatcher for the Ad Account object. It receives webhook deliveries from Meta, returns the required acknowledgement, routes events by , logs them

Google Sheets, Slack
Slack & Telegram

Type in Slack. Walk away. Get a professional PDF report and a structured Excel fix sheet delivered to Google Drive and posted back in your Slack thread — fully automated, zero manual work.

Compression, HTTP Request, Google Drive +3
Slack & Telegram

This template monitors Google Drive folder for new files, extracts text from PDFs, images, text files, CSVs, and Google Docs., reads images with meta/llama-3.2-11b-vision-instruct, structures the resu

Google Drive Trigger, Google Drive, Google Docs +3