AutomationFlowsAI & RAG › Classify and Log AI Use Cases with Anthropic and Supabase for Au-aligned…

Classify and Log AI Use Cases with Anthropic and Supabase for Au-aligned…

Original n8n title: Classify and Log AI Use Cases with Anthropic and Supabase for Au-aligned Governance

ByAdnan Tariq @adnantariq on n8n.io

Turn AI policy into a working governance process aligned to Australian Government AI.gov.au guidance.

Webhook trigger★★★★★ complexityAI-powered31 nodesAnthropicSupabaseEmail Send
AI & RAG Trigger: Webhook Nodes: 31 Complexity: ★★★★★ AI nodes: yes Added:
Classify and Log AI Use Cases with Anthropic and Supabase for Au-aligned… — n8n workflow card showing Anthropic, Supabase, Email Send integration

This workflow corresponds to n8n.io template #15879 — we link there as the canonical source.

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": "CBNe2uUfi4M1Dply",
  "name": "CYBERPULSE AI Responsible AI Governance \u2014 Australian Government-Aligned",
  "tags": [],
  "nodes": [
    {
      "id": "webhook_intake",
      "name": "When AI Governance Form Submitted",
      "type": "n8n-nodes-base.webhook",
      "onError": "continueRegularOutput",
      "position": [
        -768,
        128
      ],
      "parameters": {
        "path": "ai-governance",
        "options": {
          "allowedOrigins": "https://your-domain.example"
        },
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "validate_route",
      "name": "Validate Submission and Choose Path",
      "type": "n8n-nodes-base.function",
      "position": [
        -528,
        128
      ],
      "parameters": {
        "functionCode": "const body = $json.body || $json;\nconst get = (k) => {\n  const v = body && body[k];\n  if (v === undefined || v === null) return '';\n  return String(v).trim();\n};\nconst type = (get('type') || 'intake').toLowerCase();\nconst isEmail = (v) => v.includes('@') && v.includes('.') && !v.includes(' ');\nconst isUuid = (v) => v.length === 36 && v.split('-').length === 5;\nif (type === 'incident') {\n  const register_id = get('register_id');\n  const incident_detail = get('incident_detail');\n  const missing = [];\n  if (!isUuid(register_id)) missing.push('register_id');\n  if (!incident_detail) missing.push('incident_detail');\n  if (missing.length) return [{ json: { route: 'validation_error', responseCode: 400, error: 'Invalid incident submission', missing } }];\n  return [{ json: { route: 'incident', type, register_id, incident_detail } }];\n}\nconst data_sensitivity = get('data_sensitivity').toLowerCase();\nconst decision_impact = get('decision_impact').toLowerCase();\nconst data = { route: 'intake', type, use_case_name: get('use_case_name'), description: get('description'), requester_email: get('requester_email'), owner_email: get('owner_email'), manager_email: get('manager_email'), data_sensitivity, decision_impact, affected_users: get('affected_users'), vendor_or_inhouse: get('vendor_or_inhouse').toLowerCase(), reversibility: get('reversibility').toLowerCase() };\nconst missing = [];\nif (!data.use_case_name) missing.push('use_case_name');\nif (!data.description) missing.push('description');\nif (!isEmail(data.requester_email)) missing.push('requester_email');\nif (!['low','medium','high'].includes(data.data_sensitivity)) missing.push('data_sensitivity');\nif (!['none','advisory','automated'].includes(data.decision_impact)) missing.push('decision_impact');\nif (missing.length) return [{ json: { route: 'validation_error', responseCode: 400, error: 'Invalid intake submission', missing } }];\nreturn [{ json: data }];"
      },
      "typeVersion": 1
    },
    {
      "id": "if_validation",
      "name": "If Submission Is Invalid",
      "type": "n8n-nodes-base.if",
      "position": [
        -288,
        128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "if_validation",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.route}}",
              "rightValue": "validation_error"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "respond_validation",
      "name": "Respond with Validation Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        0,
        -80
      ],
      "parameters": {
        "options": {
          "responseCode": "={{$json.responseCode || 400}}",
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "https://your-domain.example"
              },
              {
                "name": "Access-Control-Allow-Methods",
                "value": "GET,POST,OPTIONS"
              },
              {
                "name": "Access-Control-Allow-Headers",
                "value": "content-type, authorization"
              },
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{ { error: $json.error, missing: $json.missing } }}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "if_incident",
      "name": "If Submission Is Incident",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "if_incident",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.route}}",
              "rightValue": "incident"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "anthropic_risk",
      "name": "Score AI Use Case Risk",
      "type": "@n8n/n8n-nodes-langchain.anthropic",
      "position": [
        256,
        368
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_YOUR_MODEL"
        },
        "options": {
          "system": "You are an AI governance risk-screening engine for an SME. Score the submitted AI use case across four factors. Respond with ONLY a valid JSON object, no preamble, no markdown, no code fences.\n\nOutput schema:\n{\n  \"data_sensitivity_score\": 0-3,\n  \"decision_autonomy_score\": 0-3,\n  \"affected_population_score\": 0-3,\n  \"reversibility_score\": 0-3,\n  \"total_score\": <sum 0-12>,\n  \"key_risks\": [\"short risk statement\", ...],\n  \"prohibited_flag\": true|false,\n  \"prohibited_reason\": \"string or null\"\n}\n\nScoring guide:\n- data_sensitivity: 0 none/public, 1 internal, 2 personal/PII, 3 sensitive (health/biometric/financial)\n- decision_autonomy: 0 human-only, 1 AI-assisted, 2 AI-recommends-human-approves, 3 fully automated decision\n- affected_population: 0 internal team, 1 some customers, 2 broad customer base, 3 vulnerable groups/public\n- reversibility: 0 trivially reversible, 1 reversible with effort, 2 hard to reverse, 3 irreversible/safety-critical\n- prohibited_flag = true only for unacceptable uses such as social scoring, real-time biometric surveillance, manipulation of vulnerable people, or other uses your policy forbids.",
          "maxTokens": 1024,
          "includeMergedResponse": true
        },
        "messages": {
          "values": [
            {
              "content": "=Use case: {{$json.use_case_name}}\nDescription: {{$json.description}}\nData types involved: {{$json.data_sensitivity}}\nDecision impact: {{$json.decision_impact}}\nAffected users: {{$json.affected_users}}\nVendor or in-house: {{$json.vendor_or_inhouse}}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "parse_risk_owner",
      "name": "Parse Risk and Pick Owner",
      "type": "n8n-nodes-base.function",
      "position": [
        512,
        368
      ],
      "parameters": {
        "functionCode": "const intake = $('Validate and Route').first().json;\nconst raw = String($json.merged_response || ($json.content || []).filter(c => c.type === 'text').map(c => c.text).join('') || '').replace(/```json/gi, '').replace(/```/g, '').trim();\nlet risk;\ntry { risk = JSON.parse(raw); } catch (e) { throw new Error('AI risk output was not valid JSON: ' + raw.slice(0, 300)); }\nconst total = Number(risk.total_score || 0);\nconst classification = risk.prohibited_flag === true ? 'prohibited' : (total >= 7 ? 'elevated' : 'normal');\nconst owner_email = intake.owner_email || intake.manager_email || 'user@example.com';\nreturn [{ json: { ...intake, risk_factors: risk, classification, owner_email } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "anthropic_checklist",
      "name": "Generate Oversight Checklist",
      "type": "@n8n/n8n-nodes-langchain.anthropic",
      "position": [
        768,
        368
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_YOUR_MODEL"
        },
        "options": {
          "system": "Generate a concise human-oversight checklist for a specific AI use case. Output 4-7 markdown checkbox items. No preamble. Tailor depth to the risk classification: normal = light touch, elevated = rigorous monitoring and escalation, prohibited = do not proceed until escalated.",
          "maxTokens": 512,
          "includeMergedResponse": true
        },
        "messages": {
          "values": [
            {
              "content": "=Use case: {{$json.use_case_name}}\nClassification: {{$json.classification}}\nKey risks: {{($json.risk_factors.key_risks || []).join(\", \")}}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "build_register",
      "name": "Prepare AI Register Record",
      "type": "n8n-nodes-base.function",
      "position": [
        1024,
        368
      ],
      "parameters": {
        "functionCode": "const intake = $('Parse Risk and Assign Owner').first().json;\nconst oversight_checklist = String($json.merged_response || ($json.content || []).filter(c => c.type === 'text').map(c => c.text).join('') || '').trim();\nconst now = new Date().toISOString();\nreturn [{ json: { ...intake, oversight_checklist, status: 'active', last_reviewed_at: now, evidence_log: [\n  { ts: now, event: 'created', actor: 'system', detail: 'intake classified ' + intake.classification },\n  { ts: now, event: 'notified', actor: 'system', detail: 'notification queued to requester and owner' }\n] } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "insert_register",
      "name": "Save AI Register Record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1296,
        368
      ],
      "parameters": {
        "tableId": "ai_register",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "use_case_name",
              "fieldValue": "={{$json.use_case_name}}"
            },
            {
              "fieldId": "description",
              "fieldValue": "={{$json.description}}"
            },
            {
              "fieldId": "requester_email",
              "fieldValue": "={{$json.requester_email}}"
            },
            {
              "fieldId": "owner_email",
              "fieldValue": "={{$json.owner_email}}"
            },
            {
              "fieldId": "data_sensitivity",
              "fieldValue": "={{$json.data_sensitivity}}"
            },
            {
              "fieldId": "decision_impact",
              "fieldValue": "={{$json.decision_impact}}"
            },
            {
              "fieldId": "affected_users",
              "fieldValue": "={{$json.affected_users}}"
            },
            {
              "fieldId": "vendor_or_inhouse",
              "fieldValue": "={{$json.vendor_or_inhouse}}"
            },
            {
              "fieldId": "reversibility",
              "fieldValue": "={{$json.reversibility}}"
            },
            {
              "fieldId": "risk_factors",
              "fieldValue": "={{$json.risk_factors}}"
            },
            {
              "fieldId": "classification",
              "fieldValue": "={{$json.classification}}"
            },
            {
              "fieldId": "oversight_checklist",
              "fieldValue": "={{$json.oversight_checklist}}"
            },
            {
              "fieldId": "status",
              "fieldValue": "active"
            },
            {
              "fieldId": "last_reviewed_at",
              "fieldValue": "={{$json.last_reviewed_at}}"
            },
            {
              "fieldId": "evidence_log",
              "fieldValue": "={{$json.evidence_log}}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "build_email",
      "name": "Build Governance Notification",
      "type": "n8n-nodes-base.function",
      "position": [
        1552,
        368
      ],
      "parameters": {
        "functionCode": "const source = $('Build Register Row').first().json;\nconst id = $json.id || source.id;\nconst risk = source.risk_factors || {};\nconst checklistHtml = String(source.oversight_checklist || '').replace(/\\n/g, '<br>');\nconst reason = risk.prohibited_reason ? '<p><strong>Prohibited reason:</strong> ' + risk.prohibited_reason + '</p>' : '';\nconst to = [...new Set([source.requester_email, source.owner_email].filter(Boolean))].join(',');\nconst html = '<h2>AI Governance Classification</h2><p><strong>Use case:</strong> ' + source.use_case_name + '</p><p><strong>Classification:</strong> ' + source.classification + '</p>' + reason + '<p><strong>Register ID:</strong> ' + id + '</p><h3>Oversight checklist</h3><div>' + checklistHtml + '</div><p>This record is logged in the AI register for audit purposes.</p>';\nreturn [{ json: { ...source, id, to, subject: '[AI Governance] ' + source.use_case_name + ' - classified ' + source.classification, html } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "send_email",
      "name": "Send Governance Notification",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1808,
        368
      ],
      "parameters": {
        "html": "={{$json.html}}",
        "options": {},
        "subject": "={{$json.subject}}",
        "toEmail": "={{$json.to}}",
        "fromEmail": "user@example.com"
      },
      "typeVersion": 2.1
    },
    {
      "id": "respond_success",
      "name": "Respond with Intake Result",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2064,
        368
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "https://your-domain.example"
              },
              {
                "name": "Access-Control-Allow-Methods",
                "value": "GET,POST,OPTIONS"
              },
              {
                "name": "Access-Control-Allow-Headers",
                "value": "content-type, authorization"
              },
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{ { ok: true, id: $(\"Build Notification Email\").first().json.id, classification: $(\"Build Notification Email\").first().json.classification, total_score: $(\"Build Notification Email\").first().json.risk_factors.total_score, prohibited_reason: $(\"Build Notification Email\").first().json.risk_factors.prohibited_reason || null } }}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "get_incident_row",
      "name": "Find Existing Register Record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        272,
        48
      ],
      "parameters": {
        "limit": 1,
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{$json.register_id}}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "ai_register",
        "matchType": "allFilters",
        "operation": "getAll"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "build_incident_update",
      "name": "Prepare Incident Evidence Update",
      "type": "n8n-nodes-base.function",
      "position": [
        528,
        48
      ],
      "parameters": {
        "functionCode": "const incident = $('Validate and Route').first().json;\nconst row = $json || {};\nif (!row.id) return [{ json: { route: 'incident_not_found', responseCode: 404, error: 'register_id not found', register_id: incident.register_id } }];\nconst log = Array.isArray(row.evidence_log) ? row.evidence_log : [];\nconst event = { ts: new Date().toISOString(), event: 'incident', actor: incident.requester_email || 'system', detail: incident.incident_detail };\nreturn [{ json: { ...row, route: 'incident_found', incident_detail: incident.incident_detail, evidence_log: [...log, event] } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "if_incident_found",
      "name": "If Register Record Found",
      "type": "n8n-nodes-base.if",
      "position": [
        784,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "if_incident_found",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.route}}",
              "rightValue": "incident_found"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "respond_incident_missing",
      "name": "Respond Register Not Found",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1040,
        -128
      ],
      "parameters": {
        "options": {
          "responseCode": "={{$json.responseCode || 404}}",
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "https://your-domain.example"
              },
              {
                "name": "Access-Control-Allow-Methods",
                "value": "GET,POST,OPTIONS"
              },
              {
                "name": "Access-Control-Allow-Headers",
                "value": "content-type, authorization"
              },
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{ { error: $json.error, register_id: $json.register_id } }}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "update_incident_row",
      "name": "Save Incident Evidence Update",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1040,
        80
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{$json.id}}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "ai_register",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "evidence_log",
              "fieldValue": "={{$json.evidence_log}}"
            }
          ]
        },
        "matchType": "allFilters",
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "id": "build_incident_email",
      "name": "Build Incident Notification",
      "type": "n8n-nodes-base.function",
      "position": [
        1312,
        80
      ],
      "parameters": {
        "functionCode": "const row = $('Build Incident Evidence Update').first().json;\nconst html = '<h2>AI Governance Incident Logged</h2><p><strong>Register ID:</strong> ' + row.id + '</p><p><strong>Use case:</strong> ' + row.use_case_name + '</p><p><strong>Incident:</strong> ' + row.incident_detail + '</p><p>This incident has been appended to the AI register evidence log.</p>';\nconst to = [...new Set([row.requester_email, row.owner_email, 'user@example.com'].filter(Boolean))].join(',');\nreturn [{ json: { id: row.id, to, subject: '[AI Governance Incident] ' + row.use_case_name, html } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "send_incident_email",
      "name": "Send Incident Notification",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1568,
        80
      ],
      "parameters": {
        "html": "={{$json.html}}",
        "options": {},
        "subject": "={{$json.subject}}",
        "toEmail": "={{$json.to}}",
        "fromEmail": "user@example.com"
      },
      "typeVersion": 2.1
    },
    {
      "id": "respond_incident",
      "name": "Respond Incident Logged",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1824,
        80
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "https://your-domain.example"
              },
              {
                "name": "Access-Control-Allow-Methods",
                "value": "GET,POST,OPTIONS"
              },
              {
                "name": "Access-Control-Allow-Headers",
                "value": "content-type, authorization"
              },
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{ { ok: true, id: $(\"Build Incident Email\").first().json.id, incident_logged: true } }}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "weekly_schedule",
      "name": "Every Monday Check Reviews",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -768,
        624
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "get_reviews",
      "name": "Find Reviews Due Soon",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -528,
        624
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "status",
              "keyValue": "active",
              "condition": "eq"
            },
            {
              "keyName": "next_review_due",
              "keyValue": "={{ new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString() }}",
              "condition": "lte"
            }
          ]
        },
        "tableId": "ai_register",
        "matchType": "allFilters",
        "operation": "getAll",
        "returnAll": true
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "format_review_digest",
      "name": "Build Review Reminder Digest",
      "type": "n8n-nodes-base.function",
      "position": [
        -256,
        624
      ],
      "parameters": {
        "functionCode": "const rows = items.map(i => i.json).filter(r => r && r.id);\nconst lines = rows.map(r => '<li><strong>' + r.use_case_name + '</strong> (' + r.classification + ') - due ' + r.next_review_due + ' - owner ' + (r.owner_email || 'unassigned') + '</li>').join('');\nreturn [{ json: { count: rows.length, html: '<h2>AI Governance Policy Review Digest</h2><p>' + rows.length + ' active AI register records are due for review within 30 days.</p><ul>' + (lines || '<li>No reviews due.</li>') + '</ul>', subject: '[AI Governance] ' + rows.length + ' policy reviews due within 30 days' } }];"
      },
      "typeVersion": 1
    },
    {
      "id": "send_review_digest",
      "name": "Send Review Reminder Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        0,
        624
      ],
      "parameters": {
        "html": "={{$json.html}}",
        "options": {},
        "subject": "={{$json.subject}}",
        "toEmail": "user@example.com",
        "fromEmail": "user@example.com"
      },
      "typeVersion": 2.1
    },
    {
      "id": "note_template_overview",
      "name": "Sticky Note - Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 944,
        "content": "## Responsible AI Governance\n\n### How it works\n\n1. Receives AI governance intake or incident submissions through a webhook.\n2. Validates required fields and routes invalid, incident, and new intake records.\n3. Scores new AI use cases, generates oversight tasks, and saves the record in Supabase.\n4. Sends requester, owner, and compliance notifications.\n5. Runs a weekly review digest for active AI register records due within 30 days.\n\n### Setup steps\n\n- [ ] Add Supabase credentials and create the `ai_register` table.\n- [ ] Add an AI provider credential and choose the model for risk scoring and checklist generation.\n- [ ] Add email credentials and replace the example sender and compliance addresses.\n- [ ] Replace the allowed CORS origin with your own application domain.\n- [ ] Keep the workflow inactive until credentials and table schema are configured.\n\n### Customization\n\nAdjust the scoring policy, review cadence, CORS origin, notification recipients, and governance table fields to match your internal AI governance process."
      },
      "typeVersion": 1
    },
    {
      "id": "note_intake_validation",
      "name": "Sticky Note - Intake Validation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -832,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 976,
        "height": 544,
        "content": "## Intake validation and routing\n\nThe webhook receives submissions, validates required fields, and routes the request. Invalid submissions return a clear validation response. Valid submissions continue either to the incident update path or the new AI use-case assessment path."
      },
      "typeVersion": 1
    },
    {
      "id": "note_incident_evidence",
      "name": "Sticky Note - Incident Evidence Updates",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 1744,
        "height": 432,
        "content": "## Incident evidence updates\n\nIncident submissions look up the existing `ai_register` row, append the incident to the evidence log, notify the relevant recipients, and respond with the incident status. If the register record is not found, the workflow returns a 404-style response."
      },
      "typeVersion": 1
    },
    {
      "id": "note_risk_assessment",
      "name": "Sticky Note - Risk Assessment",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 944,
        "height": 304,
        "content": "## Risk assessment and checklist\n\nNew AI use cases are scored by the AI model against sensitivity, decision impact, affected population, and reversibility. The workflow parses the structured risk output, assigns an owner, and generates a practical human-oversight checklist."
      },
      "typeVersion": 1
    },
    {
      "id": "note_register_notifications",
      "name": "Sticky Note - Register and Notifications",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 1040,
        "height": 304,
        "content": "## Register logging and notifications\n\nThe workflow saves the completed governance record to Supabase table `ai_register`, builds an HTML notification, sends it to the requester and owner, and returns the intake result to the original webhook request."
      },
      "typeVersion": 1
    },
    {
      "id": "note_review_digest",
      "name": "Sticky Note - Review Digest",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -864,
        528
      ],
      "parameters": {
        "color": 7,
        "width": 1008,
        "height": 304,
        "content": "## Weekly review digest\n\nEvery Monday, the scheduled branch finds active AI register records with reviews due in the next 30 days, formats a digest, and emails the compliance recipient so reviews are not missed."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "timezone": "UTC",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1",
    "saveManualExecutions": false,
    "saveDataErrorExecution": "none",
    "saveDataSuccessExecution": "none"
  },
  "versionId": "f3b002d7-2897-4496-9010-ca51b9be7dac",
  "connections": {
    "Find Reviews Due Soon": {
      "main": [
        [
          {
            "node": "Build Review Reminder Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score AI Use Case Risk": {
      "main": [
        [
          {
            "node": "Parse Risk and Pick Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save AI Register Record": {
      "main": [
        [
          {
            "node": "Build Governance Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Register Record Found": {
      "main": [
        [
          {
            "node": "Save Incident Evidence Update",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Register Not Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Submission Is Invalid": {
      "main": [
        [
          {
            "node": "Respond with Validation Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If Submission Is Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Submission Is Incident": {
      "main": [
        [
          {
            "node": "Find Existing Register Record",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Score AI Use Case Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Risk and Pick Owner": {
      "main": [
        [
          {
            "node": "Generate Oversight Checklist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Monday Check Reviews": {
      "main": [
        [
          {
            "node": "Find Reviews Due Soon",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare AI Register Record": {
      "main": [
        [
          {
            "node": "Save AI Register Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Incident Notification": {
      "main": [
        [
          {
            "node": "Respond Incident Logged",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Incident Notification": {
      "main": [
        [
          {
            "node": "Send Incident Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Review Reminder Digest": {
      "main": [
        [
          {
            "node": "Send Review Reminder Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Oversight Checklist": {
      "main": [
        [
          {
            "node": "Prepare AI Register Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Governance Notification": {
      "main": [
        [
          {
            "node": "Respond with Intake Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Governance Notification": {
      "main": [
        [
          {
            "node": "Send Governance Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Existing Register Record": {
      "main": [
        [
          {
            "node": "Prepare Incident Evidence Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Incident Evidence Update": {
      "main": [
        [
          {
            "node": "Build Incident Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Incident Evidence Update": {
      "main": [
        [
          {
            "node": "If Register Record Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When AI Governance Form Submitted": {
      "main": [
        [
          {
            "node": "Validate Submission and Choose Path",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Submission and Choose Path": {
      "main": [
        [
          {
            "node": "If Submission Is Invalid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

Turn AI policy into a working governance process aligned to Australian Government AI.gov.au guidance.

Source: https://n8n.io/workflows/15879/ — 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

Who is this for? Event organizers, conference planners, and marketing teams fighting registration drop-off who want 4-field forms with LinkedIn-level attendee intelligence. What problem is this workfl

Data Table, HubSpot, Email Send +4
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

@Brightdata/N8N Nodes Brightdata, Information Extractor, Google Gemini Chat +2
AI & RAG

Automatically classify incoming leads based on the sentiment of their message using Google Gemini, store them in Supabase by category, and send tailored WhatsApp messages via the official WhatsApp Clo

Google Gemini Chat, Sentiment Analysis, Supabase +1
AI & RAG

Anyone who wants to automatically aggregate their invoices or receipts. Main beneficiaries: small business owners and freelancers. Creates a folder in Google Drive for uploading invoices and receipts.

OpenAI, Google Drive, Gmail +1
AI & RAG

Automatically classifies incoming cold email replies as HOT, WARM, or COLD using AI and sends priority Telegram notifications with auto-acknowledgment for fast response times.

Stop And Error, OpenAI, Telegram +2