{
  "id": "mfKlWp31P3yJ9EYN",
  "name": "GDPR-Safe AI Chat Agent \u2014 PII Screened Before the Model (PromptLock Guard)",
  "tags": [],
  "nodes": [
    {
      "id": "94391dd4-479f-4a79-ae37-096cd0fab295",
      "name": "About this template",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 740,
        "content": "## GDPR-Safe AI Chat Agent \u2014 PII Screened Before the Model (PromptLock Guard)\n\n### How it works\n\nEvery chat message is screened by PromptLock Guard before it reaches the model. Personal data (names, emails, phone numbers, dates of birth and more) is redacted so the assistant can still answer on the clean text. The model never receives the raw personal data, and it is instructed not to ask users to provide any. Prompt-injection attempts are refused; clean messages pass straight through.\n\n### Setup steps\n\n- Install the n8n-nodes-promptlock-guard community node and add your PromptLock API key (free at promptlock.io).\n- Add your Anthropic credential to the Claude request node.\n- Activate the workflow and open the built-in chat to test.\n\n### Customization\n\nChoose which frameworks to screen and the Action on High Risk (redact, flag, block or score) on the Guard node. Ships on Redact \u2014 the mode that strips PII at every risk level. Edit the Claude prompt, or extend the Hold-for-Review lane with a Slack alert or a spreadsheet for your review queue."
      },
      "typeVersion": 1
    },
    {
      "id": "f1e177d7-cfee-4709-8323-b70bbcaf3b1c",
      "name": "Section 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        208
      ],
      "parameters": {
        "color": 4,
        "width": 340,
        "height": 532,
        "content": "### 1. Chat input\nn8n's native chat. Works in the editor immediately; toggle \"Make Chat Publicly Available\" for a hosted chat URL."
      },
      "typeVersion": 1
    },
    {
      "id": "89b12b10-4125-419f-ba53-58a53ba48c6a",
      "name": "Section 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        208
      ],
      "parameters": {
        "color": 5,
        "width": 320,
        "height": 532,
        "content": "### 2. Compliance screening\nGuard routes each message: Allow, Flag, Redact or Block.\n\nRedacted messages continue to the model with PII replaced by labels like [GDPR_EMAIL] \u2014 personal data never reaches the LLM. API errors fail closed."
      },
      "typeVersion": 1
    },
    {
      "id": "31defb82-ef4b-4d4f-aa46-ddd40cb12649",
      "name": "Section 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        208
      ],
      "parameters": {
        "color": 6,
        "width": 800,
        "height": 928,
        "content": "### 3. Reply by verdict\nClean or redacted-PII messages \u2192 Claude replies with the screened text (personal data already stripped).\n\n**Injection Detected?** catches any message carrying a prompt-injection violation \u2014 whichever verdict the Guard gave \u2014 and routes it to *Refuse* before it can reach the model.\n\nFlag \u2192 held-for-review message; extend this lane with a Slack alert or a sheet for your review queue.\nBlock / screening error \u2192 refused (fail closed)."
      },
      "typeVersion": 1
    },
    {
      "id": "c21a3959-cad1-4fd1-9ce9-22f5f5bde51b",
      "name": "When Chat Message Received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        608,
        448
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "32ce3c7b-bf6c-4b58-a5f9-2b2d5ae4355b",
      "name": "PromptLock Compliance Guard",
      "type": "n8n-nodes-promptlock-guard.promptLockGuard",
      "position": [
        960,
        496
      ],
      "parameters": {
        "resource": "prompt",
        "operation": "analyze"
      },
      "typeVersion": 1
    },
    {
      "id": "c27326a2-ee22-4c48-86af-ed7cfd34be8a",
      "name": "Injection Detected?",
      "type": "n8n-nodes-base.if",
      "position": [
        1296,
        528
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "inj1",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ ($json.promptLock && $json.promptLock.violations ? $json.promptLock.violations : []).some(v => v.type === 'prompt_injection') }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ab7e06aa-7e6f-4560-98dc-e91808d0145b",
      "name": "Claude Generates Reply",
      "type": "n8n-nodes-base.httpRequest",
      "maxTries": 3,
      "position": [
        1552,
        528
      ],
      "parameters": {
        "url": "https://api.anthropic.com/v1/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ model: 'claude-sonnet-4-6', max_tokens: 1024, messages: [{ role: 'user', content: 'You are a helpful, concise assistant for a privacy-conscious business. Personal data may appear as [GDPR_*] placeholders \u2014 treat them as already known and anonymized. Do NOT ask the user to share, repeat, or provide any personal data (names, addresses, emails, phone numbers, dates of birth, account or ID numbers) in this chat. If a request would require personal details, explain that you cannot collect that here and point them to a secure or verified channel instead. Reply conversationally to this message: ' + ($json.cleanText || $json.chatInput) }] }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            }
          ]
        },
        "nodeCredentialType": "anthropicApi"
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 2000
    },
    {
      "id": "f37272c2-0a61-4c66-9522-673ed120b389",
      "name": "Format Chat Reply",
      "type": "n8n-nodes-base.set",
      "position": [
        1792,
        528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "r1",
              "name": "output",
              "type": "string",
              "value": "={{ $json.content[0].text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9013e177-7fd7-4fd9-8acd-012fbc399cca",
      "name": "Hold for Human Review",
      "type": "n8n-nodes-base.set",
      "position": [
        1552,
        768
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "h1",
              "name": "output",
              "type": "string",
              "value": "={{ 'Thanks - your message needs a quick review by our team before I can respond (risk score ' + ($json.promptLock ? $json.promptLock.risk_score : 'n/a') + '). Someone will follow up shortly.' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7d4ea320-5ccb-41ac-88ad-1e67f6fc098a",
      "name": "Refuse Unsafe Message",
      "type": "n8n-nodes-base.set",
      "position": [
        1552,
        960
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b1",
              "name": "output",
              "type": "string",
              "value": "={{ $json.promptLock && $json.promptLock.error ? 'I can\\'t process messages right now - our compliance screening is temporarily unavailable and this assistant fails closed. Please try again shortly.' : 'I can\\'t respond to that message - it was refused by our compliance screening.' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "620c2073-ba9a-43a8-94c3-04370b1fb0d7",
  "nodeGroups": [],
  "connections": {
    "Injection Detected?": {
      "main": [
        [
          {
            "node": "Refuse Unsafe Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Claude Generates Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude Generates Reply": {
      "main": [
        [
          {
            "node": "Format Chat Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Chat Message Received": {
      "main": [
        [
          {
            "node": "PromptLock Compliance Guard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PromptLock Compliance Guard": {
      "main": [
        [
          {
            "node": "Injection Detected?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Hold for Human Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Injection Detected?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Refuse Unsafe Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}