{
  "name": "handoff",
  "nodes": [
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1.4,
      "position": [
        -208,
        384
      ],
      "id": "284c6afc-7cac-49af-86ba-8168597ad9f3",
      "name": "When chat message received",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "\u0422\u044b \u2014 \u0430\u0433\u0435\u043d\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0446\u0438\u0438 \u0441\u043f\u0443\u0442\u043d\u0438\u043a\u043e\u0432.\n\n\u0422\u0432\u043e\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u0430\u0442\u043a\u0438\u0439 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 handoff-\u043f\u0435\u0440\u0435\u0441\u043a\u0430\u0437, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439:\n\n* \u0447\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0430\u043b\u043e\u0441\u044c \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438\u0445 \u043f\u0438\u0441\u044c\u043c\u0430\u0445/\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u0445\n* \u043a\u0430\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0438\n* \u043a\u0430\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\n\n\u0422\u044b \u041e\u0411\u042f\u0417\u0410\u041d \u0441\u0442\u0440\u043e\u0433\u043e \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430:\n\n\u0418\u0421\u0422\u041e\u0427\u041d\u0418\u041a\u0418 \u0414\u0410\u041d\u041d\u042b\u0425 (\u041e\u0411\u042f\u0417\u0410\u0422\u0415\u041b\u042c\u041d\u042b)\n\n1. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0412\u0421\u0415 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0437:\n   \u2192 Postgress pgVector store 1 (\u0431\u0430\u0437\u0430 \u043f\u0440\u0430\u0432\u0438\u043b)\n   \u042d\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u043c\u0435\u044e\u0442 \u0432\u044b\u0441\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u044d\u0432\u0440\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f.\n\n2. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438\u0437:\n   \u2192 Postgress pgVector store (\u0431\u0430\u0437\u0430 CASECARD)\n   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0434\u043b\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043e\u0442\u0447\u0451\u0442\u0430.\n\n3. \u041f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0438\u0441\u0435\u043c/\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0422\u041e\u041b\u042c\u041a\u041e \u0447\u0435\u0440\u0435\u0437:\n   \u2192 tool call: \"handoff_data\"\n\n4. \u041f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 CDM/\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0422\u041e\u041b\u042c\u041a\u041e \u0447\u0435\u0440\u0435\u0437:\n   \u2192 tool call: \"validator_base\"(\u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u044b \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043f\u0438\u0441\u0430\u0442\u044c \u0432 objects \u0438\u043c\u0435\u043d\u0430 \u043e\u0431\u044c\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u044b \u0443\u0436\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u0448\u044c \u0432 \u043f\u0438\u0441\u044c\u043c\u0430\u0445, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 SATTELITE MOON, MIA-X01)\n\n\u0417\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0441\u043a\u0430\u0437 \u0438\u043b\u0438 \u0432\u044b\u0432\u043e\u0434\u044b \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u044d\u0442\u0438\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c.\n\n\u041e\u0413\u0420\u0410\u041d\u0418\u0427\u0415\u041d\u0418\u042f \u041f\u041e\u0412\u0415\u0414\u0415\u041d\u0418\u042f\n\n* \u0417\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0434\u043e\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0435 \u0444\u0430\u043a\u0442\u044b\n* \u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u0442 \u2014 \u043f\u0438\u0441\u0430\u0442\u044c: \"No data returned\"\n* \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0443\u044e  \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0434\u0438\u0430\u043b\u043e\u0433\u0430\n* \u041d\u0435 \u0441\u043f\u0435\u043a\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\n* \u041d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439\n* \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0441\u043e\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b \u0432\u044b\u0448\u0435 \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438\n\n\u041f\u041e\u0420\u042f\u0414\u041e\u041a \u041e\u0411\u0420\u0410\u0411\u041e\u0422\u041a\u0418 (\u0421\u0422\u0420\u041e\u0413\u041e)\n\n1. \u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 (pgVector store 1)\n2. \u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 CASECARD\n3. \u0412\u044b\u0437\u0432\u0430\u0442\u044c handoff_data \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439\n4. \u0412\u044b\u0437\u0432\u0430\u0442\u044c validator_base \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u0443\u0441\u0430 CDM\n5. \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043a\u043e \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c\n6. \u0421\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0441\u043a\u0430\u0437\n\n\u0424\u041e\u0420\u041c\u0410\u0422 \u0412\u042b\u0412\u041e\u0414\u0410 (\u041e\u0411\u042f\u0417\u0410\u0422\u0415\u041b\u042c\u041d\u042b\u0419)\n\nSummary:\n\n* Thread scope covered:\n* Operator transitions (if any):\n* Messages exchanged (\u043a\u0440\u0430\u0442\u043a\u043e \u043f\u043e \u0445\u0440\u043e\u043d\u043e\u043b\u043e\u0433\u0438\u0438):\n* CDMs referenced/updated:\n* New CDMs detected:\n* Operational status (ours vs counterpart):\n* Planned actions:\n* Pending expectations / monitoring items:\n\n\u0421\u0422\u0418\u041b\u042c\n\n* \u0421\u0436\u0430\u0442\u044b\u0439\n* \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439\n* \u0411\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\n* \u0411\u0435\u0437 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432\n* \u0411\u0435\u0437 \u044d\u043c\u043e\u0434\u0437\u0438\n* \u0411\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        112,
        416
      ],
      "id": "eda18062-1971-4955-acdc-581840a4accb",
      "name": "AI Agent",
      "executeOnce": true,
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4.1-mini",
          "mode": "list",
          "cachedResultName": "gpt-4.1-mini"
        },
        "builtInTools": {},
        "options": {
          "maxTokens": 5000
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        -32,
        640
      ],
      "id": "aad5cbed-090d-4f7e-bd82-7ad4aece862e",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "contextWindowLength": 2
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        192,
        640
      ],
      "id": "aa7de1b0-0695-4730-9476-241d93a3fc36",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "there is casecard",
        "tableName": "casecards",
        "topK": 3,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
      "typeVersion": 1.3,
      "position": [
        640,
        512
      ],
      "id": "0e36f4b1-c8ce-4fa5-82b6-d98cf25baa9f",
      "name": "Postgres PGVector Store",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "there is rules",
        "tableName": "rules",
        "topK": 7,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
      "typeVersion": 1.3,
      "position": [
        704,
        592
      ],
      "id": "8f780aa3-1615-462d-a92e-049d73f2d60d",
      "name": "Postgres PGVector Store1",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "typeVersion": 1.2,
      "position": [
        528,
        640
      ],
      "id": "3cdb0e60-1ed8-402b-bd91-6b5dec09d8d3",
      "name": "Embeddings OpenAI",
      "executeOnce": false,
      "alwaysOutputData": true,
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO messages\n(message_id, created_at, operator, id)\nvalues ($1, $2, $3, $4)",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "=$1 = {{ $json.message_id }} $2 = {{ $json.created_at}} $3 = {{ $json.operator }} $4 = {{ $json.id }}"
        }
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        224,
        0
      ],
      "id": "678fe1e8-cd25-4469-9cc7-e295998826a7",
      "name": "Execute a SQL query",
      "alwaysOutputData": true,
      "executeOnce": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "/**\n * n8n Function node (JavaScript)\n * INPUT: item.json.chatInput (\u0442\u0435\u043a\u0441\u0442 \u043f\u0438\u0441\u044c\u043c\u0430)\n * OUTPUT: { message_id, created_at, letter, operator }\n * letter \u0431\u0443\u0434\u0435\u0442 \u0441 \u041d\u041e\u0420\u041c\u0410\u041b\u042c\u041d\u042b\u041c\u0418 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0430\u043c\u0438 \u0441\u0442\u0440\u043e\u043a (\u043d\u0435 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439).\n */\nid = 2\nfunction pickFirstMatch(text, regex) {\n  const m = String(text || \"\").match(regex);\n  return m ? (m[1] ?? null) : null;\n}\n\nfunction extractAllEmails(text) {\n  const matches = String(text || \"\")\n    .match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g);\n  if (!matches) return [];\n  const seen = new Set();\n  const out = [];\n  for (const e of matches) {\n    const k = e.toLowerCase();\n    if (!seen.has(k)) { seen.add(k); out.push(k); }\n  }\n  return out;\n}\n\nfunction parseUtcLikeDate(s) {\n  if (!s) return null;\n  const str = String(s).trim();\n\n  // ISO (\u2026Z)\n  {\n    const d = new Date(str);\n    if (!isNaN(d.getTime()) && (str.includes(\"Z\") || str.includes(\"UTC\") || str.includes(\"utc\"))) {\n      return d.toISOString();\n    }\n  }\n\n  // \"YYYY-MM-DD HH:MM UTC\" or \"YYYY-MM-DD HH:MM:SS UTC\" or with Z\n  const m = str.match(\n    /(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*(?:\\(?UTC\\)?|Z)?/i\n  );\n  if (m) {\n    const Y = Number(m[1]), Mo = Number(m[2]), D = Number(m[3]);\n    const h = Number(m[4]), mi = Number(m[5]), se = m[6] ? Number(m[6]) : 0;\n    const d = new Date(Date.UTC(Y, Mo - 1, D, h, mi, se));\n    return isNaN(d.getTime()) ? null : d.toISOString();\n  }\n\n  // last resort\n  const d = new Date(str);\n  return isNaN(d.getTime()) ? null : d.toISOString();\n}\n\nfunction extractMessageId(letter) {\n  return (\n    pickFirstMatch(letter, /(?:^|\\n)\\s*Message\\s*ID\\s*:\\s*([^\\s\\r\\n]+)/i) ||\n    pickFirstMatch(letter, /(?:^|\\n)\\s*CDM\\s*MESSAGE[_\\s-]*ID\\s*:\\s*([^\\s\\r\\n]+)/i) ||\n    null\n  );\n}\n\nfunction extractCreatedAt(letter) {\n  const createdRaw =\n    pickFirstMatch(letter, /(?:^|\\n)\\s*Created\\s*at\\s*:\\s*([^\\r\\n]+)/i) ||\n    pickFirstMatch(letter, /(?:^|\\n)\\s*CDM\\s*creation[_\\s-]*date.*?:\\s*([^\\r\\n]+)/i) ||\n    null;\n\n  return createdRaw ? parseUtcLikeDate(createdRaw) : null;\n}\n\nfunction extractOperator(letter) {\n  // 1) Signature: \"Operator A \u2014 LUNASAT\"\n  const m = String(letter || \"\").match(/(?:^|\\n).*?\\bOperator\\s*([A-Z])\\b\\s*[\u2014-]\\s*([A-Z0-9_.-]+)/i);\n  if (m) return `${m[1]} \u2014 ${m[2]}`;\n\n  // 2) Any line \"Operator: XYZ\"\n  const opBody = pickFirstMatch(letter, /(?:^|\\n)\\s*Operator\\s*:\\s*([A-Z0-9_.-]+)/i);\n  if (opBody) return opBody;\n\n  // 3) Fallback: last email in letter (usually signature)\n  const emails = extractAllEmails(letter);\n  if (emails.length) return emails[emails.length - 1];\n\n  return null;\n}\n\nfunction normalizeLetterText(x) {\n  // \u041f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0441\u0442\u0440\u043e\u043a \u043a \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \\n \u0438 \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \\r\n  let s = String(x ?? \"\");\n\n  // \u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a\u0430\u043a \u0434\u0432\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \"\\\\n\" \u2014 \u0440\u0430\u0437\u044d\u043a\u0440\u0430\u043d\u0438\u0440\u0443\u0435\u043c\n  const hasRealNewlines = s.includes(\"\\n\") || s.includes(\"\\r\");\n  const hasEscapedNewlines = s.includes(\"\\\\n\") || s.includes(\"\\\\r\\\\n\") || s.includes(\"\\\\r\");\n\n  if (!hasRealNewlines && hasEscapedNewlines) {\n    s = s\n      .replace(/\\\\r\\\\n/g, \"\\n\")\n      .replace(/\\\\n/g, \"\\n\")\n      .replace(/\\\\r/g, \"\\n\");\n  }\n\n  // \u041d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 Windows-\u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0432 \\n\n  s = s.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n  // (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0440\u043e\u043a\n  s = s.split(\"\\n\").map(line => line.replace(/[ \\t]+$/g, \"\")).join(\"\\n\");\n\n  return s;\n}\n\nconst out = [];\n\nfor (const item of items) {\n  const raw = item.json?.chatInput;\n\n  if (raw == null) {\n    out.push({\n      json: {\n        message_id: null,\n        created_at: null,\n        letter: null,\n        operator: null,\n        error: \"chatInput is null/undefined\",\n      },\n    });\n    continue;\n  }\n\n  const letter = normalizeLetterText(raw);\n\n  const message_id = extractMessageId(letter);\n  const created_at = extractCreatedAt(letter);\n  const operator = extractOperator(letter);\n\n  out.push({\n    json: {\n      message_id,\n      created_at,\n      letter,     // <-- \u0442\u0443\u0442 \u0443\u0436\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\n      operator,\n      id,\n    },\n  });\n}\n\nreturn out;\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "id": "4d145588-b619-4e82-bbea-c8eb085c58f3",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "formTitle": "dsaz",
        "formDescription": "asdasdasd",
        "formFields": {
          "values": [
            {
              "fieldLabel": "asdas",
              "fieldType": "textarea"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.5,
      "position": [
        208,
        240
      ],
      "id": "7e52ddb9-327b-45bf-94d2-13e85d0c7e4c",
      "name": "On form submission"
    },
    {
      "parameters": {
        "mode": "insert",
        "tableName": "rules",
        "embeddingBatchSize": 150,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
      "typeVersion": 1.3,
      "position": [
        416,
        272
      ],
      "id": "35c4b0b1-33d4-4e7d-aa15-39140629b49e",
      "name": "Postgres PGVector Store2",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "typeVersion": 1.1,
      "position": [
        624,
        400
      ],
      "id": "075ca8c2-5c49-4075-8b94-b862da88beff",
      "name": "Default Data Loader"
    },
    {
      "parameters": {
        "description": "there is CDM_DATA BASE",
        "workflowId": {
          "__rl": true,
          "value": "H0mGDKsuvbZ1bAzO",
          "mode": "list",
          "cachedResultUrl": "/workflow/H0mGDKsuvbZ1bAzO",
          "cachedResultName": "Handoff_data"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "id": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('id', ``, 'string') }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        336,
        640
      ],
      "id": "a71e4514-d0e0-442e-b9c4-1243b8d406da",
      "name": "Call 'handoff_base"
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Postgres PGVector Store": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Postgres PGVector Store1": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI": {
      "ai_embedding": [
        [
          {
            "node": "Postgres PGVector Store",
            "type": "ai_embedding",
            "index": 0
          },
          {
            "node": "Postgres PGVector Store1",
            "type": "ai_embedding",
            "index": 0
          },
          {
            "node": "Postgres PGVector Store2",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Execute a SQL query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Postgres PGVector Store2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Postgres PGVector Store2",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Call 'handoff_base": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "15e15466-7d44-4708-9a03-77a28a2f54bb",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "7UJ9iCpzVgt0rgjq",
  "tags": []
}