使用 N8N 快速搭建飞书聊天机器人

2,214 阅读19分钟

N8N 是做什么的?

AI 工作流,自动化、API服务、小型表单收集系统

为什么推荐N8N?

  1. 截止 2025-4-30 的 87.4k 的Star和 23.7k 的Fork,足以证明其实用和优秀
  2. 400+的内置节点,足够满足大部分实用场景,连接各系统手拿把掐
  3. 高度拓展的系统设计,允许全定制开发自定义节点,甚至可以使用内部搭建的私有npm源
  4. 活跃的社区,1700+的参考模板,加速了N8N对内的业务流程落地
  5. 直观的界面逻辑,非常友好的拖拽交互逻辑,甚至支持输入变量的拖拽
  6. Code节点的打印深层对象和数组对开发人员很优化,直接输出结构化打印数据到控制台中

如何部署安装

下面的演示是基于docker-compose部署演示,如果想试用可以本机执行npx n8n(前提是nodejs v20.18.0+环境)

n8n/docker-compose.yml

服务是使用 Queue 的模式启动的,目的是提升系统高并发和稳定性
n8n 是主进程,未激活的测试任务会使用主进程,分发任务也是主进程做的
n8n-worker 是工作进程,处理主进程分发的任务,这里需要根据服务器配置开启进程数 ./.n8n:/home/node/.n8n 是必须需要持久化的目录,里面包含一些外部插件,密钥配置等文件
./.npmrc:/home/node/.npmrc 是做私有化配置使用的,如果你在公司内部有搭建私有npm,或者想使用淘宝npm 源可以用到
./tmp:/tmp 目录是给 n8n 写临时文件用的,比如 Write Disk,比如拉取 git 仓库到 tmp 目录等操作

version: "3.8"

x-shared: &shared
  restart: always
  image: docker.n8n.io/n8nio/n8n
  env_file:
    - .env
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./.n8n:/home/node/.n8n
    - ./.npmrc:/home/node/.npmrc
    - ./tmp:/tmp
services:
  n8n:
    <<: *shared
    ports:
      - 5678:5678

  n8n-worker:
    <<: *shared
    command: worker --concurrency=50
    depends_on:
      - n8n

n8n/.env

.env是容器启动必须变量配置文件

由于是Queue 多进程模式启动,必须要使用 PG 数据库和 Redis,且上面的 worker 进程数不应该大于PG的最大连接数

下面变量演示变量文件中没有开启官方推荐的task runner,是因为开启后Code节点console.log打印数据结构全部转成了字符串类型,但是关闭后就是按数据类型结构化输出的,调试友好,方便定位!

# 基础配置
DOMAIN_NAME=n8n.域名.com
GENERIC_TIMEZONE=Asia/Shanghai
N8N_PORT=5678
NODE_ENV=production
N8N_RELEASE_TYPE=stable
TZ=Asia/Shanghai
# 安全配置
N8N_SECURE_COOKIE=false


N8N_EDITOR_BASE_URL=https://n8n.域名.com/
WEBHOOK_URL=https://n8n.域名.com/

NODE_FUNCTION_ALLOW_BUILTIN=*
NODE_FUNCTION_ALLOW_EXTERNAL=*

# 邮件配置
N8N_SMTP_HOST=smtp.qiye.aliyun.com
N8N_SMTP_PORT=465
N8N_SMTP_USER=发送邮件的用户名
N8N_SMTP_PASS=发送邮件的密码

# PG数据库配置
DB_TYPE=postgresdb
DB_POSTGRESDB_DATABASE=db_n8n
DB_POSTGRESDB_HOST=192.168.1.1
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_SCHEMA=public
DB_POSTGRESDB_PASSWORD=数据库密码

# 加密
N8N_ENCRYPTION_KEY=这个填初次激活产生的加密key,这个非常重要

# Redis配置
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=192.168.1.1
QUEUE_BULL_REDIS_PORT=6379
QUEUE_BULL_REDIS_PASSWORD=Redis的密码
QUEUE_BULL_REDIS_DB=0
QUEUE_HEALTH_CHECK_ACTIVE=false

# 注册源
N8N_COMMUNITY_PACKAGES_REGISTRY=你的私有源地址或者淘宝的私有源地址


其他部署说明

postgresdb 和 redis 的部署这块就不多赘述了
nginx配置时需要注意下,n8n有websocket长链接的服务

开始进入到n8n Web 界面 - 安装一些常用的社区插件

n8n-nodes-feishu-lite 是比较优秀的社区插件,封装了常用的飞书接口。且作者处理 issues 的速度极其快速,给他点赞!
其他插件推荐 github.com/restyler/aw…
如何自己开发插件 github.com/n8n-io/n8n-…
插件使用注意项:安装或者卸载后刷新即可生效,但是更新插件必须要重启服务才能生效!

image.png

创建飞书企业自建应用

这里不做过多赘述,要获取到 appId 和 appScrect 配置,以方便配置事件订阅的 URL 和消息回调的 URL

事件订阅指的是:订阅后,当某个事件触发了会调用你这个 URL ,比如说机器人单聊,群聊,会话首次创建,员工入离职,状态变更等等。

消息回调指的是:机器人发送的卡片信息里面包含交互元素,比如说审批卡片,有个同意和拒绝的按钮,用户点击了同意或者拒绝后飞书就会调用消息回调 URL 告诉后台系统,然后后台系统再根据URL 的请求体参数和业务需求更新消息卡片

N8N 飞书机器人的json模板

支持事件订阅 和 事件配置的URL合法性验证
支持回调配置 和 回调配置的URL合法性验证
支持单聊和群聊回复,群聊跟单聊实现机制一致,但是群聊必须@机器人才能回复
支持50条回话上下文记录,支持对话方式开始新对话(MCP插件实现)
只支持纯文本接受处理,如果其他类型消息处理需要根据自己需要拓展

{
  "name": "N8N飞书订阅机器人 copy",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "4946e7d3-a97e-448d-ba00-c73c62b454cb",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        -360
      ],
      "id": "3d1122d1-8697-4a94-8464-185437c26080",
      "name": "Webhook",
      "webhookId": "4946e7d3-a97e-448d-ba00-c73c62b454cb"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "2129e27e-64b3-4709-8aea-1c1cd5388abe",
              "name": "encryptKey",
              "value": "获取路径:事件与回调 - 加密策略 - Encrypt Key",
              "type": "string"
            },
            {
              "id": "c75d7f68-1e87-43c4-827d-f6feaa9ecb38",
              "name": "verificationToken",
              "value": "获取路径:事件与回调 - 加密策略 - Verification Token",
              "type": "string"
            },
            {
              "id": "3cdd133d-739d-4061-bf74-0e4f65befc5f",
              "name": "requestBody",
              "value": "={{ $json.body }}",
              "type": "object"
            },
            {
              "id": "090d1681-a682-4635-83d6-bbddf011c7dc",
              "name": "feishuAccessTokenRedisKey",
              "value": "N8N:feishuChat-accessToken",
              "type": "string"
            },
            {
              "id": "25e5f158-4fae-4fae-8d39-1f362ca4adbe",
              "name": "appName",
              "value": "N8N",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        -360
      ],
      "id": "be5685dd-d2db-45a6-892c-edd200ad94f1",
      "name": "变量定义"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "32a6b4df-2701-4cb3-bddb-711c7ed7d3d6",
                    "leftValue": "={{ $json?.event?.type }}",
                    "rightValue": "p2p_chat_create",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "首次创建回话"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "ad9e3044-73b9-48ea-8dca-7ddfabde6f63",
                    "leftValue": "={{ $json?.header?.event_type }}",
                    "rightValue": "im.message.receive_v1",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "接受来自用户的消息"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "76b2ecac-96db-4d60-9bda-a62198ccebc7",
                    "leftValue": "={{ $json?.header?.event_type }}",
                    "rightValue": "im.message.message_read_v1",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "用户已经阅读了消息"
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        2640,
        -360
      ],
      "id": "eaf55642-6677-4fa6-a141-2dd538728bc0",
      "name": "判断事件",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event.message.chat_type }}",
                    "rightValue": "p2p",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "a182776e-7c1c-4709-8131-7aa80cd67041"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "单聊模式"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "a4474b0c-5642-4c8a-8550-a202accc1f0c",
                    "leftValue": "={{ $json.event.message.chat_type }}",
                    "rightValue": "group",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "群聊模式"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        2880,
        -360
      ],
      "id": "8a31b135-14e2-4b6a-9ecb-a71a7e38301d",
      "name": "判断是消息类型"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "text",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "6a835dc9-9192-4361-9a6e-ce3137201222"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "text纯文本"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "2b40df5d-decc-4225-9687-4841e0a62a4e",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "image",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "图片信息"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "1ac6814b-d572-4067-af6b-3e02165a4d41",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "post",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "富文本信息"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "885fb898-4754-48e4-b3bf-23676c0d0828",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "file",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "文件"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "a3f4975d-e1b2-4e3b-a31a-62e33c71b34f",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "audio",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "语音"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "13d2ecaa-e7ab-4918-8e29-344a3aa3795d",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "media",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "视频"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "5bc5914f-a848-4eb2-b49d-e1e33325d7e2",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "sticker",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "表情包"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "251f4694-855b-4dc6-a5fd-add8a3e427a1",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "interactive",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "卡片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "3741abad-a794-4e9d-b8a6-4ebdcf2fef0e",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "share_chat",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "分享群名片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "0ce0b5be-f7e9-4bbf-bd7c-3fe781573523",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "share_user",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "分享个人名片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "50b4b784-b9b6-4949-ab77-4abce54794ee",
                    "leftValue": "={{ $json.event.message.message_type }}",
                    "rightValue": "system",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "系统消息"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        3080,
        -360
      ],
      "id": "0f1c4859-cea9-4072-a472-d063a4ad33b2",
      "name": "判断消息卡片类型"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "message:reply",
        "message_id": "={{ $json.event.message.message_id }}",
        "msg_type": "interactive",
        "content": "={\n  \"type\": \"template\",\n  \"data\": {\n      \"template_id\": \"AAq4wfk1OUuxz\",\n      \"template_version_name\": \"1.0.0\",\n      \"template_variable\": {\n         \"title\": \"AI正在生成回复,请稍等\",\n         \"subTitle\": \"执行ID:{{$execution.id}}\",\n         \"titleColor\":\"yellow\",\n         \"content\": \"请稍等片刻...\"\n      }\n  }\n}"
      },
      "type": "n8n-nodes-feishu-lite.feishuNode",
      "typeVersion": 1,
      "position": [
        3300,
        -460
      ],
      "id": "56e153aa-9f08-461d-b495-31bb026350ea",
      "name": "飞书消息回复",
      "credentials": {
        "feishuCredentialsApi": {
          "id": "X99B4VQjXdWjQ7qL",
          "name": "N8N机器人"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const crypto = require('crypto');\n\nclass AESCipher {\n  constructor(key) {\n    const hash = crypto.createHash('sha256');\n    hash.update(key);\n    this.key = hash.digest();\n  }\n\n  decrypt(encrypt) {\n    try {\n      const encryptBuffer = Buffer.from(encrypt, 'base64');\n\n      const decipher = crypto.createDecipheriv('aes-256-cbc', this.key, encryptBuffer.slice(0, 16));\n\n      let decrypted = decipher.update(encryptBuffer.slice(16)\n        .toString('hex'), 'hex', 'utf8');\n      decrypted += decipher.final('utf8');\n      return decrypted;\n    } catch (err) {\n      return null;\n    }\n  }\n\n  encrypt(content, ivKey) {\n    try {\n      ivKey = ivKey ? Buffer.from(ivKey) : crypto.randomBytes(16);\n      let encrypted;\n      const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(this.key), ivKey);\n      cipher.setAutoPadding(true);// 自动填充\n      encrypted = cipher.update(content);\n      encrypted = Buffer.concat([ encrypted, cipher.final() ]);\n      return Buffer.concat([ ivKey, encrypted ]).toString('base64');\n    } catch (err) {\n      return null;\n    }\n  }\n}\n\nconst encryptKey = $input.first().json.encryptKey\nconst encryptData = $input.first().json.requestBody.encrypt\nconst cipher = new AESCipher(encryptKey);\nlet data = cipher.decrypt(encryptData);\n\nif(!data){\n  throw new Error(\"解密失败\")\n}\n\nconst newData = JSON.parse(data);\nreturn newData\n\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1980,
        -460
      ],
      "id": "ae8ef53a-6b42-451f-b98b-569f95ef6d6b",
      "name": "解密请求体"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "ecd35f1f-ede6-4331-bb54-3b2c5181bc6b",
              "leftValue": "={{ $json?.requestBody?.encrypt }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1760,
        -360
      ],
      "id": "6f8c9e2d-6437-4be7-8059-3f6cb0f18080",
      "name": "判断是事件订阅还是消息回调"
    },
    {
      "parameters": {
        "respondWith": "noData",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        1980,
        -260
      ],
      "id": "3b40ec7f-26e3-4cf9-a303-ae1d380c3b45",
      "name": "先回复消息再处理流程"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"challenge\": \"{{ $json.challenge }}\"\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        2420,
        -560
      ],
      "id": "0ffe20a5-603b-49ab-91ab-a9f30c729510",
      "name": "验证challenge"
    },
    {
      "parameters": {
        "respondWith": "noData",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        2420,
        -360
      ],
      "id": "06dc67d8-bc5f-4869-afbc-f6996191fb9b",
      "name": "响应空数据数据1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "e98496c8-e55e-4655-aeb4-7b2d22efb4af",
              "leftValue": "={{ $json.type }}",
              "rightValue": "url_verification",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2200,
        -460
      ],
      "id": "78af5cb3-b424-4f14-a681-7d00535359e4",
      "name": "判断是验证模式还是对话模式"
    },
    {
      "parameters": {
        "resource": "auth",
        "operation": "auth:getAccessToken"
      },
      "type": "n8n-nodes-feishu-lite.feishuNode",
      "typeVersion": 1,
      "position": [
        880,
        -360
      ],
      "id": "d7ceecc3-6dfa-4473-9647-9f708b46b94e",
      "name": "获取凭证1"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "numberInputs": 3,
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        3780,
        -340
      ],
      "id": "ceb81de4-952b-4918-93ef-57a74b18fe75",
      "name": "数据合并"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "585586d4-d1c2-4e2c-913a-b187586d6554",
              "leftValue": "={{ $json.accessToken }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        660,
        -285
      ],
      "id": "7d4f515e-78c7-4ba4-a501-46c1ea191278",
      "name": "redis数据不存在"
    },
    {
      "parameters": {
        "operation": "set",
        "key": "={{ $('变量定义').item.json.feishuAccessTokenRedisKey }}",
        "value": "={{ $json.accessToken }}",
        "keyType": "string",
        "expire": true,
        "ttl": 7200
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        1100,
        -360
      ],
      "id": "64c9642d-9dd3-43ca-8974-37ec78c3213a",
      "name": "写入",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "accessToken",
        "key": "={{ $json.feishuAccessTokenRedisKey }}",
        "keyType": "string",
        "options": {}
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        440,
        -285
      ],
      "id": "7965193b-344b-46b1-9374-cceabe5b848c",
      "name": "读取"
    },
    {
      "parameters": {
        "fieldToSplitOut": "accessToken",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        1320,
        -285
      ],
      "id": "7f8addc8-b48d-4fa6-9b0a-e2d4077ae7e3",
      "name": "accessToken"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineAll",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        1540,
        -360
      ],
      "id": "f8e20df9-5b72-4b7b-b6e6-aadb96020513",
      "name": "合并变量数据"
    },
    {
      "parameters": {
        "jsCode": "const content =  $input.first().json.event.message.content\n\nreturn {\n  type:'p2p',\n  content: JSON.parse(content)\n}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3300,
        -260
      ],
      "id": "363ecfa1-1c0e-4664-a819-0bee4a1f0734",
      "name": "text解析"
    },
    {
      "parameters": {
        "url": "=https://open.feishu.cn/open-apis/contact/v3/users/{{ $json.event.sender.sender_id.union_id }}",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "user_id_type",
              "value": "union_id"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('合并变量数据').item.json.accessToken }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3300,
        -80
      ],
      "id": "bd3d717e-1536-4fe0-9595-82bafa7f2d76",
      "name": "获取用户消息"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.content.text }}",
        "options": {
          "systemMessage": "=\n# 角色设定\n\n- **描述**: 为用户{{ $json.data.user.name }}定制的AI助手,称呼规则:英文名优先,无英文名则使用中文名的名字部分\n- **当前时间**: {{ $now.format('yyyy-MM-dd HH:mm:ss') }}\n- **重点**: 提供精准、实用的个性化帮助\n\n# 能力\n\n- **解答问题**: 提供准确信息,解释复杂概念,澄清疑惑\n- **创意支持**: 激发灵感,辅助创意工作,提供多角度思考\n- **文字处理**: 协助写作、编辑和内容优化,提升表达质量\n- **分析总结**: 压缩重点,提取关键信息,归纳要点\n\n# 原则\n\n- **准确性**: 提供准确可靠信息,不猜测,不虚构\n- **客观性**: 保持客观中立,呈现多元视角\n- **相关性**: 量身定制回答,精准满足用户需求\n- **伦理**: 遵守伦理边界,拒绝有害请求\n- **适应性**: 根据用户知识水平调整表达方式\n\n# 沟通风格\n\n- **语调**: 友善专业\n- **结构**: 简洁直接,条理分明\n- **方法**: 灵活应变,适应不同情境\n\n# 用户资料\n\n- **中文名**: {{ $json.data.user.name }}\n- **英文名**: {{ $json.data.user.en_name }}\n- **职位**: {{ $json.data.user.job_title }}\n\n# 输出\n\n- **结构**: Markdown\n\n# Markdown格式要求如下\n\n## 基本语法提示\n- 使用`#`创建标题,从`# 一级标题`到`###### 六级标题`\n- 使用`**文本**`或`__文本__`实现**粗体**\n- 使用`*文本*`或`_文本_`实现*斜体*\n- 使用`~~文本~~`实现~~删除线~~\n- 使用`- `或`* `创建无序列表\n- 使用`1. `创建有序列表\n- 使用`[链接文本](URL)`创建[链接](https://example.com)\n- 使用`![替代文本](图片URL)`插入图片\n- 使用`` `代码` ``标记`行内代码`\n- 使用` ``` `创建代码块,可指定语言:```javascript\n\n## 扩展语法提示\n- 使用`> `创建引用块\n- 使用`---`或`***`创建分隔线\n- 创建表格:\n  ```\n  | 表头1 | 表头2 |\n  | ----- | ----- |\n  | 内容1 | 内容2 |\n  ```\n- 使用`- [ ]`和`- [x]`创建任务列表\n- 支持HTML标签嵌入\n\n## 排版建议\n- 保持段落间空行以提高可读性\n- 使用适当的标题层级结构\n- 使用列表整理关键信息\n- 重要内容使用粗体或引用突出\n- 复杂概念使用表格展示\n\n## 适用场景\n- 文档编写\n- 笔记整理\n- 网站内容\n- 技术文档\n- 博客文章\n- 邮件撰写\n\n\n# 工具调用\n\n- **redis**: 当用户主动说出\"你好\",\"开始你对话\",\"结束本轮对话\",\"重新开始\"时调用"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        4560,
        -300
      ],
      "id": "2d2399c7-64ac-4bc1-be30-18462f38eaa9",
      "name": "AI Agent",
      "retryOnFail": true,
      "maxTries": 2
    },
    {
      "parameters": {
        "projectId": {
          "__rl": true,
          "value": "sei-ai-test",
          "mode": "list",
          "cachedResultName": "sei-ai-test"
        },
        "modelName": "gemini-2.5-flash-preview-04-17",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleVertex",
      "typeVersion": 1,
      "position": [
        4440,
        60
      ],
      "id": "33cf06fc-7c0f-4f20-9284-1dd5879d9d4c",
      "name": "Google Vertex Chat Model1",
      "credentials": {
        "googleApi": {
          "id": "RkgKgcfyoQuEaVpL",
          "name": "google cloud"
        }
      }
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://open.feishu.cn/open-apis/im/v1/messages/{{ $('两选一执行')?.first()?.json.data.message_id }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('合并变量数据').item.json.accessToken }}"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "content",
              "value": "={\n  \"type\": \"template\",\n  \"data\": {\n      \"template_id\": \"AAq4wfk1OUuxz\",\n      \"template_version_name\": \"1.0.1\",\n      \"template_variable\": {\n         \"title\": \"AI回复\",\n          \"subTitle\": \"执行ID:{{$execution.id}}\",\n         \"titleColor\":\"turquoise\",\n         \"content\":{{ JSON.stringify($json.output) }},\n         \"desc\":\"会话条数最大50条。如果需要新对话,直接回复重新开始或者结束本轮对话等关键词即可\"\n      }\n  }\n}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        5020,
        -300
      ],
      "id": "989a3f7f-de79-47eb-8985-b87902ccd2cc",
      "name": "更新消息2"
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('变量定义').item.json.appName }}:user:{{ $json.data.user.user_id }}:{{ $json.type }}",
        "contextWindowLength": 50
      },
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "typeVersion": 1.5,
      "position": [
        4620,
        60
      ],
      "id": "4f08752d-e676-4db9-b1b1-7b43e59aaed4",
      "name": "Redis Chat Memory",
      "credentials": {
        "redis": {
          "id": "qlx5vkJBpfBoWFFE",
          "name": "Redis account (工具服务正式)"
        }
      }
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "当用户主动说出\"你好\",\"开始你对话\",\"结束本轮对话\",\"重新开始\"时调用",
        "operation": "delete",
        "key": "={{ $('变量定义').item.json.appName }}:user:{{ $json.data.user.user_id }}:{{ $json.type }}"
      },
      "type": "n8n-nodes-base.redisTool",
      "typeVersion": 1,
      "position": [
        4780,
        60
      ],
      "id": "dd83cc83-ef13-458e-bf9c-0b106bf4641e",
      "name": "MCP-Redis",
      "credentials": {
        "redis": {
          "id": "qlx5vkJBpfBoWFFE",
          "name": "Redis account (工具服务正式)"
        }
      }
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "message:reply",
        "message_id": "={{ $json.event.message.message_id }}",
        "msg_type": "interactive",
        "content": "={\n  \"type\": \"template\",\n  \"data\": {\n      \"template_id\": \"AAq4wfk1OUuxz\",\n      \"template_version_name\": \"1.0.0\",\n      \"template_variable\": {\n         \"title\": \"不支持该消息类型\",\n         \"subTitle\": \"执行ID:{{$execution.id}}\",\n         \"titleColor\":\"red\",\n         \"content\": \"你想对该消息做什么处理呢?\"\n      }\n  }\n}"
      },
      "type": "n8n-nodes-feishu-lite.feishuNode",
      "typeVersion": 1,
      "position": [
        3300,
        160
      ],
      "id": "cbbef5a2-e3fc-476c-a4b9-5424adda93da",
      "name": "不支持的类型",
      "credentials": {
        "feishuCredentialsApi": {
          "id": "X99B4VQjXdWjQ7qL",
          "name": "N8N机器人"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const mentions = $input.first().json?.event?.message?.mentions || []\n\nconst hasMentions = mentions.some(item=>item.name === $('变量定义').first().json.appName)\nreturn [\n  {\n    hasMentions,\n    data: $input.first().json\n  }\n]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3080,
        460
      ],
      "id": "356945b1-0f88-40eb-b22e-ce5fe6950f81",
      "name": "是否有@N8N"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "d05cd340-6f1a-4ce3-be67-51cdda9faf45",
              "leftValue": "={{ $json.hasMentions }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        3300,
        460
      ],
      "id": "d42d3c67-6305-4dd8-a5e9-e676fd4fc03f",
      "name": "被提及"
    },
    {
      "parameters": {
        "jsCode": "const text = JSON.parse($input.first().json.data.event.message.content).text\nconst mentions =  $input.first().json.data.event.message.mentions\n\nlet newText = text\nmentions.forEach(item=>{\n  newText = newText.replace(item.key,\"\")\n})\nreturn  {type:'group',content: { text: newText}}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3780,
        360
      ],
      "id": "97f3fffd-174f-4132-9d75-67e01ed4f21f",
      "name": "解析text"
    },
    {
      "parameters": {
        "url": "=https://open.feishu.cn/open-apis/contact/v3/users/{{ $json.data.event.sender.sender_id.union_id }}",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "user_id_type",
              "value": "union_id"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('合并变量数据').item.json.accessToken }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3780,
        540
      ],
      "id": "1f95bbc6-96cf-4ef2-9417-933ea81e6bdb",
      "name": "获取用户消息1"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "message:reply",
        "message_id": "={{ $json.data.event.message.message_id }}",
        "msg_type": "interactive",
        "content": "={\n  \"type\": \"template\",\n  \"data\": {\n      \"template_id\": \"AAq4wfk1OUuxz\",\n      \"template_version_name\": \"1.0.0\",\n      \"template_variable\": {\n         \"title\": \"AI正在生成回复,请稍等\",\n         \"subTitle\": \"执行ID:{{$execution.id}}\",\n         \"titleColor\":\"yellow\",\n         \"content\": \"请稍等片刻...\"\n      }\n  }\n}"
      },
      "type": "n8n-nodes-feishu-lite.feishuNode",
      "typeVersion": 1,
      "position": [
        3780,
        180
      ],
      "id": "88d4d9cf-28fa-4c96-b286-ad77547b2e1d",
      "name": "飞书群消息回复"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "numberInputs": 3,
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        4100,
        320
      ],
      "id": "71d217f0-ab8b-4b84-bdd2-4bec6c5458c7",
      "name": "数据合并1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        4320,
        -300
      ],
      "id": "3a1133ad-51d9-4117-bf33-0c5c2c7cdef9",
      "name": "两选一执行"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "message:reply",
        "message_id": "={{ $json.data.event.message.message_id }}",
        "msg_type": "interactive",
        "content": "={\n  \"type\": \"template\",\n  \"data\": {\n      \"template_id\": \"AAq4wfk1OUuxz\",\n      \"template_version_name\": \"1.0.0\",\n      \"template_variable\": {\n         \"title\": \"不支持该消息类型\",\n         \"subTitle\": \"执行ID:{{$execution.id}}\",\n         \"titleColor\":\"red\",\n         \"content\": \"你想对该消息做什么处理呢?\"\n      }\n  }\n}"
      },
      "type": "n8n-nodes-feishu-lite.feishuNode",
      "typeVersion": 1,
      "position": [
        3780,
        760
      ],
      "id": "2a773c46-22b0-4af9-aef9-be8634742b00",
      "name": "不支持的类型1"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "text",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "6a835dc9-9192-4361-9a6e-ce3137201222"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "text纯文本"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "2b40df5d-decc-4225-9687-4841e0a62a4e",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "image",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "图片信息"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "1ac6814b-d572-4067-af6b-3e02165a4d41",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "post",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "富文本信息"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "885fb898-4754-48e4-b3bf-23676c0d0828",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "file",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "文件"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "a3f4975d-e1b2-4e3b-a31a-62e33c71b34f",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "audio",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "语音"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "13d2ecaa-e7ab-4918-8e29-344a3aa3795d",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "media",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "视频"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "5bc5914f-a848-4eb2-b49d-e1e33325d7e2",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "sticker",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "表情包"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "251f4694-855b-4dc6-a5fd-add8a3e427a1",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "interactive",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "卡片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "3741abad-a794-4e9d-b8a6-4ebdcf2fef0e",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "share_chat",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "分享群名片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "0ce0b5be-f7e9-4bbf-bd7c-3fe781573523",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "share_user",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "分享个人名片"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "50b4b784-b9b6-4949-ab77-4abce54794ee",
                    "leftValue": "={{ $json.data.event.message.message_type }}",
                    "rightValue": "system",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "系统消息"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        3520,
        280
      ],
      "id": "78f17c98-c2d1-48bb-8304-2247a2805cc8",
      "name": "判断群聊消息类型1"
    },
    {
      "parameters": {
        "content": "## Redis流程目的\n**为了缓存access-token,避免触发飞书频控",
        "height": 180,
        "width": 460
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        540,
        -100
      ],
      "typeVersion": 1,
      "id": "18714753-6cf2-4441-8a51-ee294dbc8e7c",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## 事件订阅\n**比如群聊,单聊,等其他事件都属于事件回调\n\n## 回调订阅\n**比如用户点击了卡片上的按钮,触发了消息回调\n\n### 注意项:\n这里都是先响应后处理流程,原因是飞书对于响应有要求,必须要3秒内响应才行",
        "height": 280,
        "width": 720
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1820,
        -860
      ],
      "typeVersion": 1,
      "id": "e1d5b41e-d1ce-44ee-bfde-0d3c7f213c66",
      "name": "Sticky Note1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        2880,
        -620
      ],
      "id": "912a0f34-3278-4351-b4b1-fdc69b44e840",
      "name": "发挥你的想象力"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        2240,
        -240
      ],
      "id": "71c7c86a-8bb2-4ea6-ab5c-bc0c624bd7f0",
      "name": "发挥你的想象力1"
    },
    {
      "parameters": {
        "content": "## 飞书回复\n**这里图简单用的飞书卡片模板搭建的"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3280,
        -640
      ],
      "typeVersion": 1,
      "id": "de0e83d1-4f43-417c-bada-1cb601433a3c",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## 变量定义里面有些配置需要更改",
        "height": 80,
        "width": 440
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        -460
      ],
      "typeVersion": 1,
      "id": "562ddeb8-f041-4d9c-b74b-5990d2136ce0",
      "name": "Sticky Note4"
    }
  ],
  "pinData": {},
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "变量定义",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "变量定义": {
      "main": [
        [
          {
            "node": "读取",
            "type": "main",
            "index": 0
          },
          {
            "node": "合并变量数据",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "判断事件": {
      "main": [
        [
          {
            "node": "发挥你的想象力",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "判断是消息类型",
            "type": "main",
            "index": 0
          }
        ],
        [],
        []
      ]
    },
    "判断是消息类型": {
      "main": [
        [
          {
            "node": "判断消息卡片类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "是否有@N8N",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "判断消息卡片类型": {
      "main": [
        [
          {
            "node": "text解析",
            "type": "main",
            "index": 0
          },
          {
            "node": "飞书消息回复",
            "type": "main",
            "index": 0
          },
          {
            "node": "获取用户消息",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "解密请求体": {
      "main": [
        [
          {
            "node": "判断是验证模式还是对话模式",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "判断是事件订阅还是消息回调": {
      "main": [
        [
          {
            "node": "解密请求体",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "先回复消息再处理流程",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "先回复消息再处理流程": {
      "main": [
        [
          {
            "node": "发挥你的想象力1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "响应空数据数据1": {
      "main": [
        [
          {
            "node": "判断事件",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "判断是验证模式还是对话模式": {
      "main": [
        [
          {
            "node": "验证challenge",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "响应空数据数据1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "飞书消息回复": {
      "main": [
        [
          {
            "node": "数据合并",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "获取凭证1": {
      "main": [
        [
          {
            "node": "写入",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "数据合并": {
      "main": [
        [
          {
            "node": "两选一执行",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "redis数据不存在": {
      "main": [
        [
          {
            "node": "获取凭证1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "accessToken",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "读取": {
      "main": [
        [
          {
            "node": "redis数据不存在",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "写入": {
      "main": [
        [
          {
            "node": "accessToken",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "accessToken": {
      "main": [
        [
          {
            "node": "合并变量数据",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "合并变量数据": {
      "main": [
        [
          {
            "node": "判断是事件订阅还是消息回调",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "text解析": {
      "main": [
        [
          {
            "node": "数据合并",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "获取用户消息": {
      "main": [
        [
          {
            "node": "数据合并",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Google Vertex Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "更新消息2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redis Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "MCP-Redis": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "是否有@N8N": {
      "main": [
        [
          {
            "node": "被提及",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "被提及": {
      "main": [
        [
          {
            "node": "判断群聊消息类型1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "飞书群消息回复": {
      "main": [
        [
          {
            "node": "数据合并1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "解析text": {
      "main": [
        [
          {
            "node": "数据合并1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "获取用户消息1": {
      "main": [
        [
          {
            "node": "数据合并1",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "数据合并1": {
      "main": [
        [
          {
            "node": "两选一执行",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "两选一执行": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "判断群聊消息类型1": {
      "main": [
        [
          {
            "node": "飞书群消息回复",
            "type": "main",
            "index": 0
          },
          {
            "node": "解析text",
            "type": "main",
            "index": 0
          },
          {
            "node": "获取用户消息1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "不支持的类型1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "32c4b9ee-c65e-4e8b-9ec9-18836c813509",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "833c78570fd4b31c71e8110775458cd1bc18942f348fe7a25e3967cc5c79ec53"
  },
  "id": "Ui7qtSjoO9tSocvg",
  "tags": []
}

复制上面的json,然后可以直接在n8n编辑器界面粘贴即可
然后自己根据Note的提示修改配置
激活后获取Production URL 再到飞书开发者后台,应用处配置链接

目前基于N8N的一些其他流程

主要是抛砖引玉,更多是给大家一个参考,下面暂时不分享配置json了,如果有需要可以私信吧。

  1. gitlab MergeRequest时使用AI进行代码审核,给出代码评分,修改意见
  2. 多语言文件的AI批量翻译
  3. jira系统的问题和评论同步至飞书项目,反之也可以飞书项目新增的评论也可以同步至jira
  4. AI客服机器人,配合上最近的MCP,这个能力可以更贴近实际做一些任务
  5. AI将仓库代码文件中文提取成i18n词条
  6. 自动化任务

使用N8N过程中一些不爽的点

  1. Task Runner开启后,console.log输出全部都是字符串,调试不直观。但是关闭后就ok了
  2. AI方面的多模态支持不太够,目前还主要是文字
  3. 开源对多语言支持不够友好,目前仅支持英文,不支持用户自主切换使用语言
  4. 表单提交系统设计的太简陋了,下拉列表不支持获取远程数据库,表单提交系统权限认证几乎等于没用

与DIFY的对比?

我这边就不对比了,可能会惹口水战。想快速尝试N8N可以看下github.com/n8n-io/n8n npx n8n 本地快速启动尝试下,或者就清楚了是否适合自己团队了