{
  "id": "1_j9-Bxn13fiv-hp8cAeG",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automatic AI reply when mentioned in a Liveblocks comment",
  "tags": [],
  "nodes": [
    {
      "id": "55c5a866-a618-4fdb-9d66-d898217f6003",
      "name": "Liveblocks Trigger",
      "type": "CUSTOM.liveblocksTrigger",
      "position": [
        -64,
        0
      ],
      "parameters": {
        "events": [
          "commentCreated"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "liveblocksWebhookSigningSecretApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1a0c859b-7ea5-4198-a861-83f6df0afbaf",
      "name": "Get a comment",
      "type": "CUSTOM.liveblocks",
      "position": [
        176,
        0
      ],
      "parameters": {
        "roomId": "={{ $json.event.data.roomId }}",
        "resource": "comment",
        "threadId": "={{ $json.event.data.threadId }}",
        "commentId": "={{ $json.event.data.commentId }}",
        "operation": "getComment"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "73646402-4f8b-4817-af91-4b88242c9cef",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        368,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3a4b15ca-e141-4096-8081-bbe359f59733",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json.mentionedUserIds }}",
              "rightValue": "__AI_AGENT"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e53009ce-0aa9-4630-a728-49c6f6755c2e",
      "name": "Get a thread",
      "type": "CUSTOM.liveblocks",
      "position": [
        592,
        0
      ],
      "parameters": {
        "roomId": "={{ $json.roomId }}",
        "resource": "thread",
        "threadId": "={{ $json.threadId }}",
        "operation": "getThread"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "50982aa6-8fc1-4f33-bb9a-e1b8860dc462",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        800,
        0
      ],
      "parameters": {
        "text": "=You are an AI assistant that can reply to comments in a thread. You have been mentioned in the latest comment and must reply.\n\nHere is the entire thread:\n\n```\n{{ JSON.stringify($json.comments, null, 2) }}\n```\n\nYou were mentioned in the last comment. Write your reply as a string.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "9d18bb25-fa44-4238-807e-0b1685883d09",
      "name": "Anthropic Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        800,
        176
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-6",
          "cachedResultName": "Claude Sonnet 4.6"
        },
        "options": {}
      },
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "7d6ea1ce-ecd4-4a1c-8490-a5915c95d4d6",
      "name": "Create a comment",
      "type": "CUSTOM.liveblocks",
      "position": [
        1136,
        0
      ],
      "parameters": {
        "roomId": "={{ $('Get a comment').item.json.roomId }}",
        "resource": "comment",
        "threadId": "={{ $('Get a comment').item.json.threadId }}",
        "createComment_userId": "__AI_AGENT",
        "createComment_bodyMode": "plainText",
        "createComment_bodyText": "={{ $json.output }}"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d414863b-9cf3-4e28-9888-a4ea6553dd67",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 432,
        "content": "## Fetch thread and generate\nIf `true`, fetch the entire comment thread, pass it to AI so it understands the full context, and ask it to write up a response."
      },
      "typeVersion": 1
    },
    {
      "id": "016a250a-59d2-4cf0-9847-803b08bc9af6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        -112
      ],
      "parameters": {
        "width": 502,
        "height": 944,
        "content": "## Automatic AI reply when mentioned in a Liveblocks comment\n \nThis example uses [Liveblocks Comments](https://liveblocks.io/comments), collaborative commenting components for React. When an AI assistant is mentioned in a thread  (e.g. \"@AI Assistant\"), it will automatically leave a response.\n\nUsing [webhooks](https://liveblocks.io/docs/platform/webhooks), this workflow is triggered when a comment is created in a thread. If the agent's ID (`\"__AI_AGENT\"`) was mentioned, an AI agent is given the entire thread context, and asked to create a response. This response is then added, and users will see it appear in their apps in real time.\n\n### Setup\nThis workflow requires a Comments app installed and webhooks set up in the Liveblocks dashboard. You can try it with a demo application:\n\n- [ ] Download the [Next.js comments example](https://liveblocks.io/examples/comments/nextjs-comments), and run it with a secret key.\n- [ ] Find `database.ts` inside the example and uncomment the AI assistant user.\n- [ ] Insert the secret key from the project into n8n nodes: \"Get a comment\", \"Get a thread\", \"Create a comment\".\n- [ ] Go to the [Liveblocks dashboard](https://liveblocks.io/dashboard), open your project and go to \"Webhooks\". Create a new webhook in your project using a placeholder URL, and selecting \"commentCreated\" events.\n- [ ] Copy your webhook secret from this page and paste it into the \"Liveblocks Trigger\" node.\n- [ ] Expose the webhook URL from the trigger, for example with `localtunnel` or `ngrok`. Copy the production URL from the \"Liveblocks Trigger\" and replace `localhost:5678` with the new URL.\n- [ ] Your workflow is now set up! Tag @AI Assistant in the application to trigger it.\n\n#### Localtunnel\nThe easiest way to expose your webhook URL:\n`npx localtunnel --port 5678 --subdomain your-name-here`\n\nThis creates a URL like:\n`https://honest-months-fix.loca.lt`\n\nThe URL you need for the dashboard looks like this:\n`https://honest-months-fix.loca.lt/webhook/9cc66974-aaaf-4720-b557-1267105ca78b/webhook`\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8bac501d-631f-43dc-aafa-7ebecaed2535",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 230,
        "height": 272,
        "content": "## Comment created\nWhen a comment is created in a room."
      },
      "typeVersion": 1
    },
    {
      "id": "00f027b5-c4cb-4643-b0b7-ebe4d80a075d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 272,
        "content": "## Check if AI mentioned\nCheck if a comment mentions the AI agent. Their ID is `\"__AI_AGENT\"` in this demo."
      },
      "typeVersion": 1
    },
    {
      "id": "85d1fc00-7999-4328-a19d-810167084e2e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1088,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 272,
        "content": "## Add response to thread\nThe response is then added as a comment in the same thread. The user ID is set to `\"__AI_AGENT\"`."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "d37e40e2-49e8-470e-8a13-c687497a2d3a",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Get a thread",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Create a comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a thread": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a comment": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Liveblocks Trigger": {
      "main": [
        [
          {
            "node": "Get a comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}