Extraer datos de contratos legales y enviar recordatorios con VLM Run, Google Workspace y Slack

Intermedio

Este es unautomatización que contiene 14 nodos.Utiliza principalmente nodos como Set, Code, Slack, Webhook, GoogleDrive. Extraer datos de contratos legales y enviar recordatorios usando VLM Run, Google Workspace y Slack

Requisitos previos
  • Bot Token de Slack o URL de Webhook
  • Punto final de HTTP Webhook (n8n generará automáticamente)
  • Credenciales de API de Google Drive
  • Credenciales de API de Google Sheets

Categoría

-
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "meta": {
    "instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "bdfebade-893c-411c-80c6-0dace07f7dc9",
      "name": "📁 Documentación de Procesamiento de Entrada",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 680,
        "content": "## 📁 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": "Monitorear Cargas de Contratos",
      "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": {
          "id": "zYyIOFMdGz258avn",
          "name": "Google Drive account 6"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "95acb226-9205-4a21-9a2d-c9792bc81de4",
      "name": "Descargar Archivo de Contrato",
      "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": {
          "id": "zYyIOFMdGz258avn",
          "name": "Google Drive account 6"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "61fa2c83-72cd-44b0-a5cd-5fbaeef5dfb1",
      "name": "🤖 Documentación de Extracción con IA",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        0
      ],
      "parameters": {
        "width": 416,
        "height": 680,
        "content": "## 🤖 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/b905e71d-8ea5-4fc2-a773-b0f92e5398e4"
      },
      "credentials": {
        "vlmRunApi": {
          "id": "B7ZYM8AfBgjnOEOl",
          "name": "VLM Run account 5"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "17996d92-afea-484c-88d3-9b2b673b1f4c",
      "name": "📊 Documentación de Almacenamiento",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## 📊 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": "Guardar en Base de Datos de Gastos",
      "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": {
          "id": "sdLQgQJjowDNfXMU",
          "name": "Google Sheets account 7"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "f752ffb1-d4eb-4d69-919d-2f4d72fb753e",
      "name": "Formatear Datos del Contrato",
      "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": "Enviar un mensaje",
      "type": "n8n-nodes-base.slack",
      "position": [
        1712,
        512
      ],
      "webhookId": "6b8dcfb9-51a9-418b-8469-4bf5b5894f2a",
      "parameters": {
        "text": "=*New Contract Processed* 📄\n• Contract ID: {{$node[\"Format Contract Data\"].json[\"Contract ID\"] || \"N/A\"}}\n• Title: {{$node[\"Format Contract Data\"].json[\"Title\"] || \"N/A\"}}\n• Parties: {{$node[\"Format Contract Data\"].json[\"Parties\"] || \"N/A\"}}\n• Effective: {{$node[\"Format Contract Data\"].json[\"Effective Date\"] || \"N/A\"}}\n• Termination: {{$node[\"Format Contract Data\"].json[\"Termination Date\"] || \"N/A\"}}\n🔗 {{$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": {
          "id": "M00QrTNTmnr6yiTS",
          "name": "Slack account 11"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "955768a3-5fac-4296-a5a3-d307a98b471c",
      "name": "Preparar Eventos de Calendario",
      "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} — 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} — 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} — 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": "Crear un evento",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        1808,
        336
      ],
      "parameters": {
        "end": "={{$json[\"end\"]}}",
        "start": "={{$json[\"start\"]}}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "sayonaraistata@gmail.com",
          "cachedResultName": "sayonaraistata@gmail.com"
        },
        "additionalFields": {
          "allday": "yes",
          "summary": "={{$json[\"summary\"]}}",
          "description": "={{$json[\"description\"]}}"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "9TLut5ZDt3hcaQEo",
          "name": "Google Calendar account 3"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dd656271-d2a3-4f8a-9df8-1da0596b2734",
      "name": "📊 Documentación de Almacenamiento1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 680,
        "content": "## 🔔 Notifications Added:\n\n1. **Slack** → Posts contract details & AI-generated summary to #all-n8n-test for team visibility.\n\n2. **Google Calendar** → Auto-creates all-day events:\n   • Effective Date\n   • Termination Date\n   • Renewal Reminder (30 days before)\n   → Helps track key contract milestones.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "99fdd61d-c6a9-4e74-989a-e56b47caf2e9",
      "name": "Nota Adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        704
      ],
      "parameters": {
        "color": 5,
        "width": 704,
        "height": 144,
        "content": "## 📝 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’t be reachable by VLM Run’s servers."
      },
      "typeVersion": 1
    },
    {
      "id": "6d26e945-a724-4e3b-a8ff-c91dd8500f5f",
      "name": "Recibir Contrato",
      "type": "n8n-nodes-base.webhook",
      "position": [
        784,
        480
      ],
      "webhookId": "b905e71d-8ea5-4fc2-a773-b0f92e5398e4",
      "parameters": {
        "path": "b905e71d-8ea5-4fc2-a773-b0f92e5398e4",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    }
  ],
  "pinData": {},
  "connections": {
    "6d26e945-a724-4e3b-a8ff-c91dd8500f5f": {
      "main": [
        [
          {
            "node": "f752ffb1-d4eb-4d69-919d-2f4d72fb753e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f752ffb1-d4eb-4d69-919d-2f4d72fb753e": {
      "main": [
        [
          {
            "node": "70c2c9c5-d950-495f-9e91-5a0b402ef739",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "95acb226-9205-4a21-9a2d-c9792bc81de4": {
      "main": [
        [
          {
            "node": "84d28c8a-b33c-4bc3-9489-846c3b412d4a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "955768a3-5fac-4296-a5a3-d307a98b471c": {
      "main": [
        [
          {
            "node": "f3301d1a-5773-4598-ba4e-71019a4966bd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2fca40fa-ac4a-4515-a1e0-295cdcbfc595": {
      "main": [
        [
          {
            "node": "95acb226-9205-4a21-9a2d-c9792bc81de4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "70c2c9c5-d950-495f-9e91-5a0b402ef739": {
      "main": [
        [
          {
            "node": "d04b627c-1b80-4692-91a3-2df61bec0b4d",
            "type": "main",
            "index": 0
          },
          {
            "node": "955768a3-5fac-4296-a5a3-d307a98b471c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Intermedio

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Intermedio
Número de nodos14
Categoría-
Tipos de nodos10
Descripción de la dificultad

Adecuado para usuarios con experiencia intermedia, flujos de trabajo de complejidad media con 6-15 nodos

Autor
Shahrear

Shahrear

@shahrear

I’m Shahrear, a Software Engineer with over 5 years of experience in full-stack development and workflow automation. I specialize in building intelligent automations using n8n, helping teams streamline operations and boost productivity. I’m also an expert in developing custom n8n nodes, with published work on npm - including the @vlm-run/n8n-nodes-vlmrun package. Linkedin - https://www.linkedin.com/in/shahrear-amin/ Email - shahrearbinamin33@gmail.com

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34