This workflow corresponds to n8n.io template #14300 — we link there as the canonical source.
This workflow follows the Agent → Anthropic Chat recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "rarpWe7vgiY8AHmp",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Analyzing uploaded Liveblocks comments attachments with AI",
"tags": [],
"nodes": [
{
"id": "ebf2043f-c524-4f1f-a112-bcc3ca70ce2e",
"name": "Liveblocks Trigger",
"type": "CUSTOM.liveblocksTrigger",
"position": [
-64,
-112
],
"parameters": {
"events": [
"commentCreated"
],
"additionalFields": {}
},
"credentials": {
"liveblocksWebhookSigningSecretApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "9204a3e9-87a9-43bb-80cf-0cda40e8ebc0",
"name": "Get a comment",
"type": "CUSTOM.liveblocks",
"position": [
176,
-112
],
"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": "40d19409-c683-49cd-8ae9-8bef1eac988b",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
368,
-112
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "93da4049-4fd2-4b5b-8126-a9c0c86e376e",
"operator": {
"type": "array",
"operation": "contains",
"rightType": "any"
},
"leftValue": "={{ $json.mentionedUserIds }}",
"rightValue": "__AI_AGENT"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "ba245bc1-35ed-4873-817c-dcc9f86c2ba4",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-128,
-224
],
"parameters": {
"color": 7,
"width": 230,
"height": 272,
"content": "## Comment created\nWhen a comment is created in a room."
},
"typeVersion": 1
},
{
"id": "40e4f97f-4c97-4a24-8a87-2e2b933fed8e",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
-224
],
"parameters": {
"color": 7,
"width": 624,
"height": 272,
"content": "## Check if AI mentioned and attachment uploaded\nCheck if a comment has an attachment, and if it mentions the AI agent. Their ID is `\"__AI_AGENT\"` in this demo."
},
"typeVersion": 1
},
{
"id": "f3124ad9-f874-49f0-9e7f-62fd0f6eea0c",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
784,
-224
],
"parameters": {
"color": 7,
"width": 384,
"height": 272,
"content": "## Fetch attachment IDs\nIf there are attachments, loop through every attachment and fetch its URL."
},
"typeVersion": 1
},
{
"id": "44ad1915-f785-40b5-a289-d99bc163a50a",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2496,
-224
],
"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
},
{
"id": "fcebab59-f7a8-407a-b963-0e0c400d7cd0",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-736,
-224
],
"parameters": {
"width": 534,
"height": 992,
"content": "## Analyzing uploaded Liveblocks comments attachments with AI\n\n### How it works\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. Additionally, it will analyze any PDf or image attachments in the comments, and use them to help it respond.\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\"`) it will create a response. If a PDF or image file is uploaded, these will be analyzed by Anthropic and used as context. 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- [ ] 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 and add attachments 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": "51bf57e0-fb1f-4dab-8f20-ee2dafe4683a",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
816,
-112
],
"parameters": {
"jsCode": "return $input.first().json.attachments.map((item) => ({ id: item.id }));"
},
"typeVersion": 2
},
{
"id": "292b839a-a63b-4965-9177-b17382434760",
"name": "Get attachment1",
"type": "CUSTOM.liveblocks",
"position": [
1024,
-112
],
"parameters": {
"roomId": "={{ $('Get a comment').item.json.roomId }}",
"resource": "attachment",
"attachmentId": "={{ $json.id }}"
},
"credentials": {
"liveblocksApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "57affdfc-dbf7-455e-a089-55085186541d",
"name": "Analyze document1",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"position": [
1488,
-112
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-6",
"cachedResultName": "claude-sonnet-4-6"
},
"options": {},
"resource": "document",
"documentUrls": "={{ $json.url }}"
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "799b8b8d-9829-4d82-a447-e44d8ace841e",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
1232,
-112
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4de5fd1b-488d-48e6-be52-e60470484186",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/pdf"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9f419375-66a9-402d-82a2-fe61f82c2af0",
"operator": {
"type": "string",
"operation": "startsWith"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "image/"
}
]
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"typeVersion": 3.4
},
{
"id": "861b0731-4a5d-486b-befa-fc4cfb151525",
"name": "Analyze image",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"position": [
1488,
48
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-6",
"cachedResultName": "claude-sonnet-4-6"
},
"options": {},
"resource": "image",
"imageUrls": "={{ $('Get attachment1').item.json.url }}"
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "d4779db5-6db4-4373-8380-e85a14cb0365",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1792,
-112
],
"parameters": {
"numberInputs": 3
},
"typeVersion": 3.2
},
{
"id": "b6d0ea12-82ab-4e3f-8bfc-d39ef99c6882",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"position": [
1488,
224
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "d56dee2e-0089-42d4-b657-fb7657dc1074",
"name": "mimeType",
"type": "string",
"value": "={{ $json.mimeType }}"
},
{
"id": "7cdec271-69f5-4146-909d-fe49799fe164",
"name": "name",
"type": "string",
"value": "={{ $json.name }}"
},
{
"id": "82b7ff0e-4bc7-43f2-bb6c-91075b016ab8",
"name": "message",
"type": "string",
"value": "Cannot analyze files of this type"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0544e919-f532-4bb9-b2a9-32e498faf93a",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2208,
-112
],
"parameters": {
"text": "=You're responding to a comment left by a users. There are some file attachments attached to the comment. You've just done an analysis of the images, this is your analysis:\n\n```\n{{ JSON.stringify($json.result, null, 2) }}\n```\n\nRespond to the users prompt using the file analysis reply. This is what the user asked you:\n\n\"\"\"\n{{ $('Get a comment').item.json.bodyPlain }}\n''''",
"options": {},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "6229e5ba-5754-4a4a-8fd6-9d0e6d78e829",
"name": "Anthropic Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
2208,
80
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-5-20250929",
"cachedResultName": "Claude Sonnet 4.5"
},
"options": {}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "0d14b116-f71e-46c0-9663-f4d3434fd65e",
"name": "Code in JavaScript1",
"type": "n8n-nodes-base.code",
"position": [
2000,
-112
],
"parameters": {
"jsCode": "return { result: $input.all() };"
},
"typeVersion": 2
},
{
"id": "60dc9f02-8f1f-4d97-8876-45c39ed2214c",
"name": "Create a comment1",
"type": "CUSTOM.liveblocks",
"position": [
2576,
-112
],
"parameters": {
"roomId": "={{ $('Get a comment').first().json.roomId }}",
"resource": "comment",
"threadId": "={{ $('Get a comment').first().json.threadId }}",
"createComment_userId": "__AI_AGENT",
"createComment_bodyMode": "plainText",
"createComment_bodyText": "={{ $json.output }}"
},
"credentials": {
"liveblocksApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b65aff57-08a0-48fe-9b44-4540a28c867c",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-224
],
"parameters": {
"color": 7,
"width": 480,
"height": 608,
"content": "## Analyze attachments\nIf Anthropic can analyze the attachment (i.e PDF or image), feed it through an analyzer. Otherwise, say you can't analyze the file type."
},
"typeVersion": 1
},
{
"id": "f39b4b1a-6c91-49e4-ae1d-e0903333ae7a",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1712,
-224
],
"parameters": {
"color": 7,
"width": 416,
"height": 304,
"content": "## Merge the analyses\nMerge the analyses back into a single list"
},
"typeVersion": 1
},
{
"id": "cc55ab1d-0121-4dac-940c-6540d6daf0dd",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
2160,
-224
],
"parameters": {
"color": 7,
"width": 304,
"height": 464,
"content": "## Create AI response\nAsk AI to write a response to the original comment, with its analysis context"
},
"typeVersion": 1
},
{
"id": "59b3ffe4-4e79-4984-86b3-2e137b3a3192",
"name": "If1",
"type": "n8n-nodes-base.if",
"position": [
592,
-112
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "3a4b15ca-e141-4096-8081-bbe359f59733",
"operator": {
"type": "array",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.attachments }}",
"rightValue": "__AI_AGENT"
},
{
"id": "93da4049-4fd2-4b5b-8126-a9c0c86e376e",
"operator": {
"type": "array",
"operation": "contains",
"rightType": "any"
},
"leftValue": "={{ $json.mentionedUserIds }}",
"rightValue": "__AI_AGENT"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "89a79d5b-a318-4097-b846-b20bda0e2938",
"name": "AI Agent1",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
672,
208
],
"parameters": {
"text": "=Respond to the users message: {{ $('Get a comment').item.json.bodyPlain }}",
"options": {},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "6de37a66-cdab-4611-aa19-1ab05e4a0d6d",
"name": "Anthropic Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
672,
400
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-5-20250929",
"cachedResultName": "Claude Sonnet 4.5"
},
"options": {}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "2db5795e-9526-464a-aedb-12e272f5f074",
"name": "Create a comment",
"type": "CUSTOM.liveblocks",
"position": [
1008,
208
],
"parameters": {
"roomId": "={{ $('Get a comment').first().json.roomId }}",
"resource": "comment",
"threadId": "={{ $('Get a comment').first().json.threadId }}",
"createComment_userId": "__AI_AGENT",
"createComment_bodyMode": "plainText",
"createComment_bodyText": "={{ $json.output }}"
},
"credentials": {
"liveblocksApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "fa2f17d3-deae-4e25-bd0a-5a9abcc1e2ca",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
96
],
"parameters": {
"color": 7,
"width": 528,
"height": 448,
"content": "## Ignore attachments and respond\nIf there are no attachments, AI generates a response to the comment, and it's added to the thread. The user ID is set to `\"__AI_AGENT\"`."
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "6a66c646-72fa-4e6d-a6d6-6d3041d20012",
"connections": {
"If": {
"main": [
[
{
"node": "If1",
"type": "main",
"index": 0
}
]
]
},
"If1": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Analyze document1",
"type": "main",
"index": 0
}
],
[
{
"node": "Analyze image",
"type": "main",
"index": 0
}
],
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Create a comment1",
"type": "main",
"index": 0
}
]
]
},
"AI Agent1": {
"main": [
[
{
"node": "Create a comment",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 2
}
]
]
},
"Analyze image": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Get a comment": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Get attachment1": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Analyze document1": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Get attachment1",
"type": "main",
"index": 0
}
]
]
},
"Liveblocks Trigger": {
"main": [
[
{
"node": "Get a comment",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Anthropic Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Anthropic Chat Model1": {
"ai_languageModel": [
[
{
"node": "AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
anthropicApiliveblocksApiliveblocksWebhookSigningSecretApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This example uses Liveblocks 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. Additionally, it will analyze any PDf or image attachments in the comments, and use…
Source: https://n8n.io/workflows/14300/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This example uses Liveblocks Storage, a sync engine created by Liveblocks that allows you to create collaborative applications like Figma, Pitch, and Spline. When we fetch the Storage value for a room
This example uses Liveblocks 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.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
This template and YouTube video goes over 5 different implementations of evaluations within n8n. Categorization Correctness Tools used String similarity Helpfulness
SMS Outreach Engine: Service providers. Uses agent, lmChatAnthropic, httpRequest, googleSheets. Event-driven trigger; 60 nodes.