{
  "nodes": [
    {
      "id": "ae3cbbb0-1987-4457-b91f-d1a766e09fb7",
      "name": "When Executed by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -180,
        -60
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "message"
            },
            {
              "name": "sender"
            },
            {
              "name": "chatid"
            },
            {
              "name": "linkedinprofile",
              "type": "array"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "0c10e97f-1de0-493e-9eda-a36507f40429",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        980,
        -60
      ],
      "parameters": {
        "text": "=Sender Name: {{ $('Isolate parent workflow data for AI').item.json.sender }}\nSender Message: {{ $('Isolate parent workflow data for AI').item.json.message }}\nMy Name: Your Name\n\nIf found, the linkedin profile will be below, pay close attention to the number of followers and connections: \n{{ $('When Executed by Another Workflow').item.json.linkedinprofile.toJsonString() }}",
        "options": {
          "systemMessage": "=You are an expert professional assistant designed to help generate smart, personalized responses to LinkedIn messages.\n\nYou will be provided with:\n1. The **incoming message** and name from a LinkedIn user.\n2. A **database of past requests and responses**. These are known message types and the preferred replies.\n3. Context about the assistant's voice and tone.\n\n### Your Objective:\n- First, scan the database for any message that closely matches the incoming LinkedIn message. If a match is found, use the **corresponding response** as a base \u2014 you may slightly tailor it if needed (e.g., change names or dates).\n- If no close match is found, generate a **new, thoughtful reply** based on the message content, tone guidelines, and best practices in business networking. If you do not have a direct link or URL to provide from the Request Database, do not reference a website or URL. Instead say a variation of let me get back to you on that and see what I can find. \n\n### Tone Guidelines:\n- Friendly, confident, and professional \u2014 but never robotic.\n- Lightly personalized. Use the sender\u2019s name if available.\n- Avoid sounding like a sales pitch.\n- Keep replies concise and natural, like something you'd actually send on LinkedIn.\n\n### When generating a new message:\n- Acknowledge the sender\u2019s message.\n- Add a relevant, helpful comment or question to continue the conversation.\n- Keep the tone warm and open-ended.\n\n### Output format:\nOnly output the message text that should be sent to the user. Do not explain your reasoning. If you do not have a direct link to provide, do not reference a website or URL. Instead say let me get back to you on that and see what I can find. \n\nLet\u2019s begin.\nRequest Database:\n\n{{ $json.dbObject.join('\\n\\n----\\n\\n') }}\n\nWhen responding, use the following format:\n{\n\t\"output\": \"message response\",\n\t\"found\": true\n}\nFor output output the message response, for found output a boolean, true if an example is found in the Request Database, false if a response is not found. The output is going to slack so ensure you escape your outputs like new lines. "
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "46cefba2-2107-4d41-b270-8442d2aae09b",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1100,
        180
      ],
      "parameters": {
        "sessionKey": "={{ $('Isolate parent workflow data for AI').item.json.chatid }}",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "3a1e8f2d-5ea9-4f31-b489-93fca3c8442e",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        920,
        180
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "gpt-4o"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2a69d1d4-5c30-4cc1-930b-7b72cd1c0ed1",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1260,
        180
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"output\": \"message response\",\n\t\"found\": true\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "bb9a7e05-d641-4caa-9fcc-7b1d39dd62d7",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        -380
      ],
      "parameters": {
        "color": 7,
        "width": 668,
        "height": 718,
        "content": "![hctiapi](https://uploads.n8n.io/templates/openai.png)\n## Generate Automated response\nThe AI bot receives not only the message from LinkedIn, but also LinkedIn user context, such as the number of followers and connections, allowing for tailored responses. For example if a user asks to meet, but they don't meet a certain number of followers threshold, they are politely declined. However if an influencer reaches out, they are automatically given a booking link to ensure that high priority requests are immediately followed up on. "
      },
      "typeVersion": 1
    },
    {
      "id": "a7f5f2b3-bc0c-450e-bbd8-60a01dc4b202",
      "name": "Isolate parent workflow data for AI",
      "type": "n8n-nodes-base.set",
      "position": [
        20,
        -60
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "91a1191e-bac0-4b8b-b263-a03c63435470",
              "name": "sender",
              "type": "string",
              "value": "={{ $json.sender }}"
            },
            {
              "id": "0f8c17c8-d598-4840-8b89-8dbdcd529231",
              "name": "message",
              "type": "string",
              "value": "={{ $json.message }}"
            },
            {
              "id": "c9132b69-5e0e-4ccf-86bb-0e4cfa734860",
              "name": "chatid",
              "type": "string",
              "value": "={{ $json.chatid }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ca7625b3-2c2a-48c5-82b5-61a00ac95c81",
      "name": "Get Request Router Directory Database",
      "type": "n8n-nodes-base.notion",
      "position": [
        220,
        -60
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "1da5b6e0-c94f-8086-80b6-eab8e340d60e",
          "cachedResultUrl": "https://www.notion.so/1da5b6e0c94f808680b6eab8e340d60e",
          "cachedResultName": "RequestRouterDB"
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ffa17cbf-a9ae-4427-8aa4-a07ab97bf60b",
      "name": "Format DB data for AI Context",
      "type": "n8n-nodes-base.set",
      "position": [
        420,
        -60
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c4ac8c33-a220-4c07-bc0d-dc7ba7cc068e",
              "name": "dbObject",
              "type": "string",
              "value": "=Request Example: {{ $json.name }}\n--\nRequest Description: {{ $json.property_request_description }}\n--\nRequest Action: {{ $json.property_request_action }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "96980e0e-632a-49dc-9cbb-a487d117e2af",
      "name": "Aggregate DB objects into one item",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        620,
        -60
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "dbObject"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d66e6cc9-2955-4d45-a65b-ffc734f9a4cf",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -380
      ],
      "parameters": {
        "color": 7,
        "width": 1006,
        "height": 640,
        "content": "![notion](https://uploads.n8n.io/templates/notionlogo.png)\n## Get routing Database data\nAn AI bot that does not get smarter over time is not a useful bot. That is why this bot references a shared internal database where requests routing can be updated without having to touch the n8n workflows. When a request comes in that does not have a standardized process, the AI will generate a response based on its model training. You can use this as a starting point, but when this becomes a pattern, simply updating the notion database instantly upgrades the AI bot. Not only that, but others can update the database, not only giving the AI context, but also creating a centralized location for standardized processes for handling different request types. This can be adapted for any platform, not just linkedIn, such as shared email inboxes, shared social media pages, and even for support requests. "
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Format DB data for AI Context": {
      "main": [
        [
          {
            "node": "Aggregate DB objects into one item",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Isolate parent workflow data for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate DB objects into one item": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Isolate parent workflow data for AI": {
      "main": [
        [
          {
            "node": "Get Request Router Directory Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Request Router Directory Database": {
      "main": [
        [
          {
            "node": "Format DB data for AI Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}