AutomationFlowsAI & RAG › Modify Liveblocks Storage with Anthropic Claude

Modify Liveblocks Storage with Anthropic Claude

Original n8n title: Modify Liveblocks Storage with JSON Patch and Anthropic Claude

ByLiveblocks @liveblocks on n8n.io

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, we're fetching the state of the multiplayer document which users are…

Event trigger★★★★☆ complexityAI-powered17 nodesCustomAgentAnthropic ChatOutput Parser Structured
AI & RAG Trigger: Event Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #14301 — 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 →

Download .json
{
  "id": "siRmitBmFbvNMw_elDq6R",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Modify Liveblocks Storage with JSON Patch",
  "tags": [],
  "nodes": [
    {
      "id": "6e1dccd1-9468-4674-8d5b-ca7a6d97eada",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -240,
        -32
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "24255aba-7d7d-417a-9890-4da3962fec00",
      "name": "Create a room",
      "type": "CUSTOM.liveblocks",
      "position": [
        -48,
        -32
      ],
      "parameters": {
        "operation": "createRoom",
        "createRoom_id": "={{ $execution.id }}",
        "createRoom_defaultAccesses": "={{ [] }}"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4a11137e-f359-4c83-9718-502c01ecf18d",
      "name": "Patch room storage",
      "type": "CUSTOM.liveblocks",
      "position": [
        144,
        -32
      ],
      "parameters": {
        "body": "[\n  {\n    \"op\": \"add\",\n    \"path\": \"/shapes\",\n    \"value\": [\n      {\n        \"id\": \"rect-1\",\n        \"type\": \"rectangle\",\n        \"x\": 100,\n        \"y\": 150,\n        \"width\": 200,\n        \"height\": 100,\n        \"color\": \"#ff0000\"\n      },\n      {\n        \"id\": \"circle-1\",\n        \"type\": \"circle\",\n        \"x\": 300,\n        \"y\": 200,\n        \"radius\": 50,\n        \"color\": \"#00ff00\"\n      }\n    ]\n  }\n]",
        "roomId": "={{ $json.id }}",
        "resource": "storage",
        "operation": "patchStorageDocument"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "43afa742-6fe4-4071-a86b-1d6e4307d396",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        592,
        -32
      ],
      "parameters": {
        "text": "=You are a JSON patch generatgor. All you return is JSPN patch operations. Here is the current document:\n\n```\n{{ JSON.stringify($json.shapes, null, 2) }}\n```\n\nHere is how you must modify the document:\n\n\"\"\"\nAdd a blue circle, and make the square orange. \n\"\"\"\n\nApply this change to `/shapes`.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "5bfc5dd6-0439-4365-9faf-60ecca8405a2",
      "name": "Get room storage",
      "type": "CUSTOM.liveblocks",
      "position": [
        400,
        -32
      ],
      "parameters": {
        "roomId": "={{ $execution.id }}",
        "resource": "storage",
        "operation": "getStorageDocument",
        "q_getStorageDocument_format": "json"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "443bd8f9-2d50-451a-ada7-4d797906009c",
      "name": "Anthropic Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        592,
        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": "f4daa4dd-4106-46f2-82e8-8c91e75bada5",
      "name": "Patch room storage1",
      "type": "CUSTOM.liveblocks",
      "position": [
        912,
        -32
      ],
      "parameters": {
        "body": "={{ $json.output }}",
        "roomId": "={{ $execution.id }}",
        "resource": "storage",
        "operation": "patchStorageDocument"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "91207bbf-a8c3-4424-90f4-f2f65700b5a7",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        736,
        176
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "={\n  \"type\": \"array\",\n  \"items\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"op\": {\n        \"type\": \"string\",\n        \"enum\": [\"add\", \"remove\", \"replace\"]\n      },\n      \"path\": {\n        \"type\": \"string\"\n      },\n      \"value\": {}\n    },\n    \"required\": [\"op\", \"path\"]\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "2b0083c0-9367-45b3-9a1e-4adc057dde49",
      "name": "Get room storage1",
      "type": "CUSTOM.liveblocks",
      "position": [
        1216,
        -32
      ],
      "parameters": {
        "roomId": "={{ $execution.id }}",
        "resource": "storage",
        "operation": "getStorageDocument",
        "q_getStorageDocument_format": "json"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "890b299e-fc1d-450b-9d11-4f508085f668",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -160
      ],
      "parameters": {
        "width": 336,
        "height": 1008,
        "content": "## Modify Liveblocks Storage with JSON Patch\n\n### How it works\nThis example uses [Liveblocks Storage](https://liveblocks.io/docs/ready-made-features/multiplayer/sync-engine/liveblocks-storage), a sync engine created by [Liveblocks](https://liveblocks.io) that allows you to create collaborative applications like Figma, Pitch, and Spline. When we fetch the Storage value for a [room](https://liveblocks.io/docs/concepts#Rooms), we're fetching the state of the multiplayer document which users are collaborating on.   \n\nIn this workflow example, our document holds a list of shapes, like a drawing tool. Here's a rectangle, for example:\n\n```\n{\n  \"id\": \"rect-1\",\n  \"type\": \"rectangle\",\n  \"x\": 100,\n  \"y\": 150,\n  \"width\": 200,\n  \"height\": 100,\n  \"color\": \"#ff0000\"\n}\n```\n\nPicture this hooked up to a design tool like Figma, with the user asking AI to edit their document.\n\nIn these nodes, to generates a [JSON Patch](https://liveblocks.io/docs/guides/modifying-storage-via-rest-api-with-json-patch) operation from the user's request (\"Add a blue circle, and make the square orange\") and applies it to the collaborative document. \n\nAs soon as the JSON Patch operation has run, each user's design tool in their web browser will update with the changes in real time.\n\nAdditionally, we're setting presence in the room, which means that the AI will appear in the document's live avatar stacks while it works, before disappearing shortly after.\n\n### Setup\nNo setup required. Replace the trigger with any you like to use this workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "755f766e-03ef-4a68-9c38-ffd3df1e2f98",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 288,
        "content": "## Create a room\nCreate a multiplayer room and initialize it with a Storage value. In a real app, this'll already be created."
      },
      "typeVersion": 1
    },
    {
      "id": "cb17c385-0125-421a-81d4-643267f0bf67",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 480,
        "content": "## Patching Storage with AI\nGetting the full Storage value, passing it to AI, and asking it to run a user query on the data. The AI is told to return JSON Patch operations, and is then applied to Storage. On the front end, the room updates in real time."
      },
      "typeVersion": 1
    },
    {
      "id": "8c76fbef-ee98-4f95-a3e9-735e395aeb11",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 294,
        "height": 288,
        "content": "## Check value\nChecking the final value after applying the operation."
      },
      "typeVersion": 1
    },
    {
      "id": "b4e7c6eb-7cd7-4330-b9ce-c629e87ab06c",
      "name": "Set presence in a room",
      "type": "CUSTOM.liveblocks",
      "position": [
        432,
        464
      ],
      "parameters": {
        "roomId": "={{ $execution.id }}",
        "operation": "setPresence",
        "setPresence_ttl": null,
        "setPresence_userId": "__AI_AGENT",
        "setPresence_userInfo": "{\n  \"name\": \"AI Assistant\",\n  \"avatar\": \"https://liveblocks.io/api/avatar?u=__AI_AGENT&agent=true\"\n}"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5444c0cb-e9a4-4282-bdc2-1906e0fb0f29",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 326,
        "height": 240,
        "content": "## Show presence\nShow AI presence in the app's avatar stack."
      },
      "typeVersion": 1
    },
    {
      "id": "2721aedc-d0cf-484c-8243-671837003c22",
      "name": "Set presence in a room1",
      "type": "CUSTOM.liveblocks",
      "position": [
        880,
        464
      ],
      "parameters": {
        "roomId": "={{ $execution.id }}",
        "operation": "setPresence",
        "setPresence_ttl": 2,
        "setPresence_userId": "__AI_AGENT",
        "setPresence_userInfo": "{\n  \"name\": \"AI Assistant\",\n  \"avatar\": \"https://liveblocks.io/api/avatar?u=__AI_AGENT&agent=true\"\n}"
      },
      "credentials": {
        "liveblocksApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a883b6ad-ac74-47c5-b0f3-8893e4794f78",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 326,
        "height": 240,
        "content": "## Hide presence\nTell the AI presence to expire in 2 seconds."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "abc3c565-0fb3-47e8-b22f-b2edb33d2b98",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Patch room storage1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a room": {
      "main": [
        [
          {
            "node": "Patch room storage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get room storage": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set presence in a room",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Patch room storage": {
      "main": [
        [
          {
            "node": "Get room storage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Patch room storage1": {
      "main": [
        [
          {
            "node": "Get room storage1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set presence in a room1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic 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
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Create a room",
            "type": "main",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

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, we're fetching the state of the multiplayer document which users are…

Source: https://n8n.io/workflows/14301/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow is designed for marketers, founders, agencies, and product teams who want to understand how real customers talk about a product category, market, or problem space.

Reddit, Agent, Output Parser Structured +3
AI & RAG

Template Carnaval - time instagram. Uses toolWorkflow, lmChatOpenAi, memoryBufferWindow, agent. Event-driven trigger; 56 nodes.

Tool Workflow, OpenAI Chat, Memory Buffer Window +10
AI & RAG

This workflow streamlines academic paper development through a multi-agent AI architecture that collects references, drafts individual sections autonomously, compiles the manuscript, and exports a pro

Form Trigger, HTTP Request, Anthropic Chat +4
AI & RAG

This workflow is designed for marketers, founders, agencies, and content teams who want to generate static ad creatives faster from minimal brand input.

HTTP Request, Output Parser Structured, Google Drive +3
AI & RAG

&gt; ⚠️ Self-hosted only — This template uses a community node () and cannot run on n8n Cloud.

Airtable, HTTP Request, @Mendable/N8N Nodes Firecrawl +3