8
n8n 中文网amn8n.com

智能供应商合同续签与提醒工作流(使用 GPT 4.1 mini)

高级

这是一个Document Extraction, Multimodal AI领域的自动化工作流,包含 21 个节点。主要使用 If, Code, Slack, EmailSend, GoogleSheets 等节点。 使用 GPT-4.1 mini、Slack 和 Gmail 自动化供应商合同续签与提醒

前置要求
  • Slack Bot Token 或 Webhook URL
  • Google Sheets API 凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "DYAmOE9mHdq9X8eT",
  "meta": {
    "instanceId": "4a2e6764ba7a6bc9890d9225f4b21d570ce88fc9bd57549c89057fcee58fed0f",
    "templateId": "5453",
    "templateCredsSetupCompleted": true
  },
  "name": "智能供应商合同续签与提醒工作流(使用 GPT 4.1 mini)",
  "tags": [
    {
      "id": "5HqPDYxcmr92h5gG",
      "name": "Finance Workflow",
      "createdAt": "2025-08-02T13:47:30.790Z",
      "updatedAt": "2025-08-02T13:47:30.790Z"
    }
  ],
  "nodes": [
    {
      "id": "c14ab271-f79e-4b40-99f4-4a67cef3988a",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1472,
        1456
      ],
      "parameters": {
        "width": 540,
        "height": 528,
        "content": "## 1. 工作流每日早上 6 点触发"
      },
      "typeVersion": 1
    },
    {
      "id": "7608b8d6-1acb-43f6-ad33-0cef8401e633",
      "name": "便签 7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2544,
        1120
      ],
      "parameters": {
        "width": 1024,
        "height": 1696,
        "content": "# 📝 智能供应商合同续签与提醒工作流(使用 GPT 4.1 mini)"
      },
      "typeVersion": 1
    },
    {
      "id": "a7c8a69b-d5bb-4b7d-abef-8be18c0d2f83",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        2256
      ],
      "parameters": {
        "width": 1020,
        "height": 596,
        "content": "![Alt text](https://wisestackai.s3.ap-southeast-1.amazonaws.com/Screenshot+2025-08-03+at+7.59.45%E2%80%AFPM.png \"可选标题文本\")"
      },
      "typeVersion": 1
    },
    {
      "id": "e0a78a50-7d76-4ce5-b240-6bb38a04f5ea",
      "name": "查找即将到期的供应商",
      "type": "n8n-nodes-base.code",
      "position": [
        -544,
        1648
      ],
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of items) {\n  const data = item.json;\n\n  const endDate = new Date(data[\"Contract End Date\"]);\n  const noticePeriod = parseInt(data[\"Notice Period (days)\"], 10);\n\n  // Calculate the date when the reminder should be sent\n  const reminderDate = new Date(endDate);\n  reminderDate.setDate(reminderDate.getDate() - noticePeriod);\n\n  // If today's date >= reminder date, it's time to remind\n  if ($today >= reminderDate && $today <= endDate) {\n    results.push({\n      json: {\n        ...data,\n        remind: true,\n        reminderDate: reminderDate.toISOString().split(\"T\")[0],\n        daysUntilExpiry: Math.floor((endDate - $today) / (1000 * 60 * 60 * 24))\n      }\n    });\n  }\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "8517796c-9c66-4c74-9c0e-b0050e495870",
      "name": "OpenAI 聊天模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -48,
        2080
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "PPSwAKeLQYgAPobT",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c7a565b9-97ca-4685-913b-80f01f9f9c09",
      "name": "结构化输出解析器",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        80,
        2080
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"subject\": \"California\",\n\t\"body\": \"\",\n  \"original_json\":\"\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "909772f9-a143-4c8d-b7b9-482eb450d428",
      "name": "提醒财务联系人并等待审批",
      "type": "n8n-nodes-base.slack",
      "position": [
        320,
        1872
      ],
      "webhookId": "bf20ed1a-2179-4efb-bfa2-b1a5fa585d6d",
      "parameters": {
        "select": "channel",
        "message": "={{ $json.output.subject }}\n{{ $json.output.body }}",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeAmount": 8
            }
          }
        },
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0989EJ7Z6K",
          "cachedResultName": "automation"
        },
        "operation": "sendAndWait",
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "fDHHxMgQm69z0h5T",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f07fa613-050d-4416-ab36-24050854bf0d",
      "name": "编写电子邮件模板",
      "type": "n8n-nodes-base.code",
      "position": [
        752,
        1872
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const record = JSON.parse($('Vendor reminder agent').item.json.output.original_json)\n\nconst vendorName = record[\"Vendor Name\"];\nconst vendorEmail = record[\"Vendor Email\"];\nconst serviceType = record[\"Service Type\"];\nconst contractEndDate = new Date(record[\"Contract End Date\"]).toDateString();\nconst financeContact = record[\"Finance Contact\"];\nconst financeEmail = record[\"Contact Email\"];\nconst renewalType = record[\"Renewal Type\"];\nconst contractValue = record[\"Contract Value (USD)\"];\n\nconst subject = `Contract Extension: ${vendorName} - ${serviceType}`;\n\nconst htmlBody = `\n  <div style=\"font-family: Arial, sans-serif; color: #333; line-height: 1.6;\">\n    <p>Dear ${vendorName} Team,</p>\n\n    <p>We are reaching out to initiate the contract extension process for your <strong>${serviceType}</strong> service. According to our records, the current contract is set to end on <strong>${contractEndDate}</strong>.</p>\n\n    <p>Key contract details:</p>\n    <ul>\n      <li><strong>Vendor:</strong> ${vendorName}</li>\n      <li><strong>Service Type:</strong> ${serviceType}</li>\n      <li><strong>Renewal Type:</strong> ${renewalType}</li>\n      <li><strong>Contract Value:</strong> $${contractValue}</li>\n    </ul>\n\n    <p>If any changes are required for the upcoming term or if you need us to provide any documentation, kindly let us know by replying to this email.</p>\n\n    <p>Best regards,<br/>\n    ${financeContact}<br/>\n    <a href=\"mailto:${financeEmail}\">${financeEmail}</a><br/>\n    Finance Team</p>\n  </div>\n`;\n\nreturn {\n  to: vendorEmail,\n  subject,\n  html: htmlBody\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "92b106a8-712e-4be8-a95d-a71e8032f0f2",
      "name": "供应商提醒代理",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        -80,
        1872
      ],
      "parameters": {
        "text": "=Here is the contract info:\n{{ $json.toJsonString()}}",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are a helpful assistant that drafts professional email reminders to finance contacts about upcoming or overdue vendor contract renewals.\\n\\n## Instructions:\\n- Use a clear, polite, and informative tone.\\n- The email should include:\\n  - Vendor name and service type\\n  - Contract end date\\n  - Renewal type (Manual or Auto-Renew)\\n  - Days left until expiration (or if overdue)\\n  - Contract value (if available)\\n  - Notes field (if provided)\\n- Address the finance contact by name.\\n- Mention next steps if renewal is manual.\\n- Keep the email concise but informative.\\n\\n## Output format:\\n- `subject`: A short subject line for the email\\n- `body`: The full email body (plain text or simple HTML)\\n\\nNow write the subject and body."
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "43d8ff59-2359-4dbe-bc5b-4fa341f6266d",
      "name": "获取供应商合同列表",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -768,
        1648
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zdDgKyL0sY54By57Yz4dNokQC_oIbVxcCKeWJ6PADBM/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zdDgKyL0sY54By57Yz4dNokQC_oIbVxcCKeWJ6PADBM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zdDgKyL0sY54By57Yz4dNokQC_oIbVxcCKeWJ6PADBM/edit?usp=drivesdk",
          "cachedResultName": "Vendors"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "L670Nly6gZGo71br",
          "name": "Google Sheets account 2"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "e1ef73e4-980d-4b47-a715-4dc071d6a35c",
      "name": "是否为自动续签合同?",
      "type": "n8n-nodes-base.if",
      "position": [
        -320,
        1648
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "31b61f50-4cc8-4c0c-a761-a1b16d1a9078",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json[\"Renewal Type\"] }}",
              "rightValue": "=Auto-Renew"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e6316dbe-ef76-4240-bfdd-6dc1ca0d52db",
      "name": "发送手动延期合同电子邮件",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        976,
        1872
      ],
      "webhookId": "2cfc6b7b-220e-441b-a89f-0b14f7feb07c",
      "parameters": {
        "html": "={{ $json.html }}",
        "options": {},
        "subject": "={{ $json.subject }}",
        "toEmail": "={{ $json.to }}"
      },
      "credentials": {
        "smtp": {
          "id": "Cqc9p9Z5PHj2MHzn",
          "name": "SMTP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d6947406-9340-4d1d-b274-1b180019c67e",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        896
      ],
      "parameters": {
        "width": 1036,
        "height": 436,
        "content": "![Alt text](https://wisestackai.s3.ap-southeast-1.amazonaws.com/Screenshot+2025-08-03+at+7.56.19%E2%80%AFPM.png \"可选标题文本\")"
      },
      "typeVersion": 1
    },
    {
      "id": "b6b47449-df79-495b-9d79-f0003b6144d2",
      "name": "编写 Slack 消息",
      "type": "n8n-nodes-base.code",
      "position": [
        -16,
        1488
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $json;\n\nconst vendorName = item[\"Vendor Name\"];\nconst serviceType = item[\"Service Type\"];\nconst contractEndDate = new Date(item[\"Contract End Date\"]).toDateString();\nconst renewalType = item[\"Renewal Type\"];\nconst contractValue = item[\"Contract Value (USD)\"];\nconst financeContact = item[\"Finance Contact\"];\nconst slackId = item[\"Slack ID\"];\nconst vendorEmail = item[\"Vendor Email\"];\nconst notes = item[\"Notes\"];\nconst daysUntil = item[\"daysUntilExpiry\"];\n\nconst message = `\n:bell: *Upcoming Auto-Renewal Notice*\n\nHi ${financeContact},\n\nThe contract with *${vendorName}* for *${serviceType}* is set to *auto-renew* in *${daysUntil} days* — on *${contractEndDate}*.\n\n> 💰 Contract Value: $${contractValue.toLocaleString()}\n> 📝 Renewal Type: ${renewalType}\n> 🗒️ Notes: ${notes}\n\nIf you wish to change this behavior or prevent auto-renewal, please send an email to the vendor at: *${vendorEmail}* before the renewal date.\n\nLet us know if you need help drafting the message or reviewing the terms.\n\nThanks,  \nFinance Automation Bot\n`;\n\nreturn {\n      slack_message: message,\n      slack_target: slackId\n    }"
      },
      "typeVersion": 2
    },
    {
      "id": "a7d66e99-4447-4c79-8b63-660bc77c1c5c",
      "name": "向财务通知自动续签合同",
      "type": "n8n-nodes-base.slack",
      "position": [
        304,
        1488
      ],
      "webhookId": "bf20ed1a-2179-4efb-bfa2-b1a5fa585d6d",
      "parameters": {
        "text": "={{ $json.slack_message }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0989EJ7Z6K",
          "cachedResultName": "automation"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "fDHHxMgQm69z0h5T",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "374f879f-6f9b-46fd-a510-ce60e2c29b51",
      "name": "便签说明4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        1616
      ],
      "parameters": {
        "width": 1484,
        "height": 676,
        "content": "![Alt text](https://wisestackai.s3.ap-southeast-1.amazonaws.com/Screenshot+2025-08-03+at+7.55.29%E2%80%AFPM.png \"可选标题文本\")"
      },
      "typeVersion": 1
    },
    {
      "id": "9291730f-742b-4fb3-9468-94f81bc8c987",
      "name": "每日调度器",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1232,
        1648
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1574e09b-04a5-49b0-b1f6-d82d69ed40a5",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        1456
      ],
      "parameters": {
        "width": 524,
        "height": 528,
        "content": "## 2. 获取供应商合同列表并查找即将到期合同"
      },
      "typeVersion": 1
    },
    {
      "id": "b6a74f00-3bad-484f-8b39-ab95f0601d03",
      "name": "便签说明5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        1360
      ],
      "parameters": {
        "width": 620,
        "height": 320,
        "content": "## 3.1 向财务团队通知自动续签合同"
      },
      "typeVersion": 1
    },
    {
      "id": "e22dffff-56ce-4c92-80a1-4ef987c24e41",
      "name": "便签 6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        1712
      ],
      "parameters": {
        "width": 620,
        "height": 496,
        "content": "## 3.2 向财务团队发送手动合同延期通知"
      },
      "typeVersion": 1
    },
    {
      "id": "a218ee9b-80bc-4a50-bbac-8690026f3fca",
      "name": "## 为什么选择 4o 模型?👆",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        1712
      ],
      "parameters": {
        "width": 620,
        "height": 496,
        "content": "## 4. 向供应商发送电子邮件以启动合同延期流程"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8176c31e-1552-4674-bd0a-ec6f4aab7ea5",
  "connections": {
    "Daily Scheduler": {
      "main": [
        [
          {
            "node": "Get vendor contract list",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Vendor reminder agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Compose slack message": {
      "main": [
        [
          {
            "node": "Notify auto-renew contract to finance",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Vendor reminder agent": {
      "main": [
        [
          {
            "node": "Remind Finance Contact & Waiting For Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compose email template": {
      "main": [
        [
          {
            "node": "Send manual extend contract email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find expiring vendor(s)": {
      "main": [
        [
          {
            "node": "Is auto-renew contract?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is auto-renew contract?": {
      "main": [
        [
          {
            "node": "Compose slack message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Vendor reminder agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get vendor contract list": {
      "main": [
        [
          {
            "node": "Find expiring vendor(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Vendor reminder agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Send manual extend contract email": {
      "main": [
        []
      ]
    },
    "Remind Finance Contact & Waiting For Approval": {
      "main": [
        [
          {
            "node": "Compose email template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 文档提取, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量21
分类2
节点类型10
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Trung Tran

Trung Tran

@trungtran

Empowering small and medium businesses with smart automation and practical AI, no big tech team required. Reach out: lets@automatewith.me

外部链接
在 n8n.io 查看

分享此工作流