id: ai-gdpr-dpia-assistant
namespace: company.legal
description: |
GDPR Data Protection Impact Assessment (DPIA) assistant using RAG
on official GDPR regulation text.
inputs:
- id: processing_activity
type: STRING
displayName: Describe the data processing activity
defaults: |
We plan to deploy an AI-powered employee monitoring system that
tracks screen activity, keystroke patterns, and application usage
to measure productivity. Data is stored in an EU-hosted cloud for
12 months and shared with department managers.
- id: data_categories
type: SELECT
displayName: Categories of personal data involved
defaults: Employee behavioral data
values:
- Employee behavioral data
- Customer transaction data
- Health and biometric data
- Children's data
- Location and tracking data
- Criminal offence data
- Large-scale profiling data
tasks:
# Step 1, Ingest the official GDPR regulation text into a vector store
# for Retrieval-Augmented Generation (RAG). This ensures the agent's
# analysis is grounded in the actual legal text, not hallucinated.
- id: ingest_gdpr_text
type: io.kestra.plugin.ai.rag.IngestDocument
description: Ingest official GDPR regulation into vector embeddings for RAG
provider:
type: io.kestra.plugin.ai.provider.MistralAI
modelName: mistral-embed
embeddings:
type: io.kestra.plugin.ai.embeddings.KestraKVStore
drop: true
documentSplitter:
maxSegmentSizeInChars: 1000
maxOverlapSizeInChars: 200
splitter: RECURSIVE
fromExternalURLs:
- https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32016R0679&format=TXT
- https://www.edpb.europa.eu/system/files/2024-02/edpb_guidelines_042023_calculationofadministrativefines_en.pdf
# Step 2, Run a DPIA assessment grounded in the ingested GDPR articles.
# The agent retrieves relevant articles from the vector store and uses
# web search to find recent EDPB guidelines and DPA enforcement decisions.
- id: dpia_assessment
type: io.kestra.plugin.ai.rag.ChatCompletion
description: Generate a DPIA report grounded in GDPR articles and EDPB guidance
chatProvider:
type: io.kestra.plugin.ai.provider.MistralAI
# Mistral Large, a European AI model hosted in EU data centers by
# Mistral AI (Paris, France). Choosing an EU-based provider is a
# deliberate data sovereignty decision: legal prompts containing
# personal data descriptions stay within EU jurisdiction.
#
# Alternative: use a LOCAL model for full air-gapped compliance:
# type: io.kestra.plugin.ai.provider.Ollama
# endpoint: http://ollama:11434
# modelName: mistral-large
modelName: mistral-large-2512
embeddingProvider:
type: io.kestra.plugin.ai.provider.MistralAI
modelName: mistral-embed
embeddings:
type: io.kestra.plugin.ai.embeddings.KestraKVStore
contentRetrievers:
- type: io.kestra.plugin.ai.retriever.TavilyWebSearch
maxResults: 5
chatConfiguration:
temperature: 0.1
maxToken: 4096
systemMessage: |
You are a senior Data Protection Officer and GDPR legal expert.
You conduct Data Protection Impact Assessments (DPIAs) as required
by Article 35 of the GDPR.
IMPORTANT RULES:
- ALWAYS cite specific GDPR articles (e.g., "Article 35(3)(a)")
- Reference relevant EDPB guidelines and WP29 opinions when applicable
- Use the retrieved GDPR text as your primary legal source
- Use web search results for recent enforcement decisions and guidance
- Be precise about legal obligations vs. recommendations
- Flag any processing that would require prior consultation with the
supervisory authority under Article 36
- Output in structured Markdown format
prompt: |
Conduct a full DPIA for the following processing activity:
PROCESSING ACTIVITY: {{ inputs.processing_activity }}
DATA CATEGORIES: {{ inputs.data_categories }}
Structure your assessment as follows:
## 1. DPIA Necessity Assessment
Determine whether a DPIA is mandatory under Article 35(3) and EDPB
guidelines. List each triggering criterion that applies.
## 2. Systematic Description of Processing (Article 35(7)(a))
- Purpose and legal basis (Article 6, and Article 9 if special categories)
- Data subjects and data types
- Data recipients and transfers (Chapter V implications)
- Retention period and storage location
## 3. Necessity and Proportionality (Article 35(7)(b))
- Is the processing necessary for the stated purpose?
- Could the purpose be achieved with less data (data minimisation, Art. 5(1)(c))?
- What is the legal basis and is it sufficient?
## 4. Risk Assessment (Article 35(7)(c))
For each identified risk, assess:
- Likelihood (Low / Medium / High)
- Severity (Low / Medium / High)
- Risk level (combining both)
- Affected rights and freedoms
## 5. Mitigation Measures (Article 35(7)(d))
Propose specific technical and organisational measures:
- Technical safeguards (encryption, pseudonymisation, access controls)
- Organisational measures (policies, training, DPO involvement)
- Data subject rights mechanisms (Article 12-22)
## 6. Residual Risk & Prior Consultation
- Assess remaining risk after mitigation
- State whether prior consultation under Article 36 is required
- Recommend next steps
# Step 3, Export the DPIA report to a Google Sheet for the legal register.
# Each execution creates a new spreadsheet so the DPO can archive it.
- id: format_report
type: io.kestra.plugin.scripts.python.Script
containerImage: python:3.11-slim
inputFiles:
report.md: "{{ outputs.dpia_assessment.outputText }}"
outputFiles:
- dpia_report.csv
script: |
import csv
with open("report.md") as f:
report = f.read()
sections = [s.strip() for s in report.split("## ") if s.strip()]
with open("dpia_report.csv", "w", newline="") as f:
w = csv.writer(f)
w.writerow(["Section", "Content"])
for section in sections:
parts = section.split("\n", 1)
title = parts[0].strip()
content = parts[1].strip() if len(parts) > 1 else ""
w.writerow([title, content])
- id: create_sheet
type: io.kestra.plugin.googleworkspace.sheets.CreateSpreadsheet
title: "DPIA, {{ inputs.data_categories }}, {{ now() | date('yyyy-MM-dd') }}"
- id: load_report
type: io.kestra.plugin.googleworkspace.sheets.Load
spreadsheetId: "{{ outputs.create_sheet.spreadsheetId }}"
from: "{{ outputs.format_report.outputFiles['dpia_report.csv'] }}"
format: CSV
range: "Sheet1"
# Step 4, Notify the privacy-legal Slack channel with a link to the report.
- id: notify_slack
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
messageText: "*DPIA Report Ready*
*Processing Activity:* {{ inputs.processing_activity | truncate(120) }}
*Data Categories:* {{ inputs.data_categories }}
<{{ outputs.create_sheet.spreadsheetUrl }}|Open DPIA Report in Google
Sheets>"
pluginDefaults:
- type: io.kestra.plugin.ai.provider.MistralAI
values:
apiKey: "{{ secret('MISTRAL_API_KEY') }}"
- type: io.kestra.plugin.ai.retriever.TavilyWebSearch
values:
apiKey: "{{ secret('TAVILY_API_KEY') }}"
- type: io.kestra.plugin.googleworkspace.sheets.CreateSpreadsheet
values:
serviceAccount: "{{ secret('GCP_SERVICE_ACCOUNT_JSON') }}"
- type: io.kestra.plugin.googleworkspace.sheets.Load
values:
serviceAccount: "{{ secret('GCP_SERVICE_ACCOUNT_JSON') }}"
- type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
values:
url: "{{ secret('SLACK_WEBHOOK') }}"