{
  "nodes": [
    {
      "id": "3f180ecc-96b8-420a-b1d2-3f9f3a18315b",
      "name": "Webhook - User Input",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -656,
        320
      ],
      "parameters": {
        "path": "guardrails-demo",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "e65aee97-5b9e-41f5-97a6-9ac6c77ba038",
      "name": "Extract Text",
      "type": "n8n-nodes-base.code",
      "position": [
        -432,
        320
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json.body;\nconst text = (input.message || input.body || input.text || '').trim();\nreturn { json: { text: text, source: input.source || 'unknown' } };"
      },
      "typeVersion": 2
    },
    {
      "id": "31489997-5f6a-4a5b-af70-a1e579e7037e",
      "name": "Input Guardrails",
      "type": "@n8n/n8n-nodes-langchain.guardrails",
      "position": [
        -208,
        320
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "guardrails": {
          "pii": {
            "value": {
              "type": "all"
            }
          },
          "jailbreak": {
            "value": {
              "threshold": 0.8
            }
          },
          "secretKeys": {
            "value": {
              "permissiveness": "strict"
            }
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c68c1928-2202-410a-88b2-8b6d03a26332",
      "name": "Input Guardrails LLM",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -160,
        480
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c1f2c53f-1f05-4d14-9289-e9512ca5a29d",
      "name": "AI - Generate Response",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        144,
        64
      ],
      "parameters": {
        "text": "=You are a helpful customer support assistant. Respond to the following inquiry in a professional, concise manner. Do not include any URLs, links, or references to external websites. Do not reveal any internal system details, API keys, or credentials.\n\nCustomer message: {{ $('Extract Text').item.json.text }}\n\nRespond directly and helpfully.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "7786e44c-dd3d-467f-b637-b42aee651203",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        224,
        288
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "267cdddd-2e23-46aa-820b-8bd2dbda1f9a",
      "name": "Output Guardrails",
      "type": "@n8n/n8n-nodes-langchain.guardrails",
      "position": [
        496,
        176
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "guardrails": {
          "nsfw": {
            "value": {
              "threshold": 0.8
            }
          },
          "secretKeys": {
            "value": {
              "permissiveness": "strict"
            }
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "91e488cf-65e6-4196-a1f4-e556825e9944",
      "name": "Output Guardrails LLM",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        576,
        336
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "54d0c810-619e-419e-9209-5ff693293f32",
      "name": "Respond - Safe Output",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        848,
        80
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'success', response: $('AI - Generate Response').item.json.output }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "bbe97fb1-f4c6-4e6d-b1ed-7615f8dd1562",
      "name": "Respond - Flagged Output (Fallback)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        848,
        272
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'output_flagged', fallback: 'Thank you for your message. A team member will follow up shortly.' }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "68d7bea8-52c8-4989-a3ca-493be57fd99a",
      "name": "Respond - Input Blocked",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        176,
        656
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'input_blocked', message: 'Your message could not be processed. Please rephrase and try again.' }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1a5644f4-d40c-4461-9254-ddce454fdbce",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1312,
        -16
      ],
      "parameters": {
        "width": 528,
        "height": 816,
        "content": "## Input + Output Guardrails\n\n### How it works\n1. **Webhook** receives user input via POST request.\n2. **Extract Text** (Code node) pulls the message content from the payload.\n3. **Input Guardrails** (Guardrails node + LLM) checks for blocked keywords, prompt injection patterns, and PII. Flagged inputs are blocked and return an error response.\n4. **AI - Generate Response** (AI Agent + OpenAI) processes clean inputs and generates a response.\n5. **Output Guardrails** (Guardrails node + LLM) scans the AI response for unexpected URLs, leaked secrets, and content policy violations. Flagged outputs fall back to a safe templated response.\n\n### Setup\n- Connect **OpenAI credentials** (or another provider) to both Guardrails LLM nodes and the AI Agent's Chat Model\n- Copy the Webhook test URL and send test inputs, including some with PII (e.g., fake SSNs) or injection attempts (e.g., \"ignore your instructions\") to see guardrails in action\n- Review the Guardrails node configurations to customize which checks are active\n\n### Customization\n- Add custom keyword lists to the Input Guardrails for your domain (e.g., competitor names, profanity)\n- Adjust the Output Guardrails to enforce your specific content policies\n\n\nThis template is a learning companion to the Production AI Playbook, a  series that explores strategies, shares best practices, and provides practical examples for building reliable AI systems in n8n.  \n\n\nThis template is a learning companion to the Production AI Playbook, a series that explores strategies, shares best practices, and provides practical examples for building reliable AI systems in n8n.  \n\nhttps://go.n8n.io/PAP-D&A-Blog"
      },
      "typeVersion": 1
    },
    {
      "id": "33ca027e-38b0-476e-a5ae-8578651d995a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 480,
        "content": "## Receive & Extract"
      },
      "typeVersion": 1
    },
    {
      "id": "7a4e8c15-c028-461e-9b22-acab31817b99",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 480,
        "content": "## Input Guardrails"
      },
      "typeVersion": 1
    },
    {
      "id": "6f5e4da2-3a84-4ef0-bd3a-d3fa8be6ba6d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 480,
        "content": "## AI Generation"
      },
      "typeVersion": 1
    },
    {
      "id": "5aba8f71-5a6b-4060-a21d-de79f039ebe6",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 480,
        "content": "## Output Guardrails"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Extract Text": {
      "main": [
        [
          {
            "node": "Input Guardrails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Input Guardrails": {
      "main": [
        [
          {
            "node": "AI - Generate Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Input Blocked",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI - Generate Response",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Output Guardrails": {
      "main": [
        [
          {
            "node": "Respond - Safe Output",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Flagged Output (Fallback)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Input Guardrails LLM": {
      "ai_languageModel": [
        [
          {
            "node": "Input Guardrails",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - User Input": {
      "main": [
        [
          {
            "node": "Extract Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Output Guardrails LLM": {
      "ai_languageModel": [
        [
          {
            "node": "Output Guardrails",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI - Generate Response": {
      "main": [
        [
          {
            "node": "Output Guardrails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}