法律契約データを抽出し、VLM Run、Google Workspace、Slackを使ってリマインド送信

中級

これは自動化ワークフローで、14個のノードを含みます。主にSet, Code, Slack, Webhook, GoogleDriveなどのノードを使用。 法律契約データを抽出し、VLM Run、Google Workspace、Slackを用いてアラートを送信

前提条件
  • Slack Bot Token または Webhook URL
  • HTTP Webhookエンドポイント(n8nが自動生成)
  • Google Drive API認証情報
  • Google Sheets API認証情報

カテゴリー

-
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
  "meta": {
    "instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "bdfebade-893c-411c-80c6-0dace07f7dc9",
      "name": "📁 入力処理ドキュメンテーション",
      "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": "契約アップロードの監視",
      "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": "契約ファイルのダウンロード",
      "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": "🤖 AI抽出ドキュメンテーション",
      "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": "📊 ストレージドキュメンテーション",
      "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": "経費データベースへの保存",
      "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": "契約データのフォーマット",
      "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": "メッセージの送信",
      "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": "カレンダーイベントの準備",
      "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": "イベントの作成",
      "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": "📊 ストレージドキュメンテーション1",
      "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": "付箋メモ3",
      "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": "契約の受信",
      "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
          }
        ]
      ]
    }
  }
}
よくある質問

このワークフローの使い方は?

上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。

このワークフローはどんな場面に適していますか?

中級

有料ですか?

このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。

ワークフロー情報
難易度
中級
ノード数14
カテゴリー-
ノードタイプ10
難易度説明

経験者向け、6-15ノードの中程度の複雑さのワークフロー

作成者
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

外部リンク
n8n.ioで表示

このワークフローを共有

カテゴリー

カテゴリー: 34