HR & Employee Data
Protect employee PII when using AI for HR workflows, recruiting, and internal documentation while respecting works-council and GDPR obligations
Protect employee personal data (names, salary, national IDs, dates of birth, contact details) when using AI to draft HR documents, summarize personnel files, and answer employee questions.
The Problem
HR teams handle some of the most sensitive personal data in the company: national identifiers, dates of birth, salary and compensation, bank details, health-related absences, and performance notes. AI can speed up drafting reference letters, summarizing personnel files, screening applications, and answering routine policy questions. But every one of those tasks pulls employee PII into the prompt.
In the EU, employee data sits under both GDPR and, in codetermined companies, works-council (Betriebsrat) agreements that constrain how personnel data may be processed and who may see it. Sending raw salary figures or a national ID to a third-party LLM provider is a data-minimization and access-control problem, not just a privacy nicety. Naive redaction breaks the workflow: strip every name from a team roster and the AI can no longer draft per-person feedback; strip the salary and it cannot summarize a compensation review.
How OGuardAI Solves It
OGuardAI sits between your HR application and the AI model. Employee identifiers and compensation are tokenized with safe metadata, so the model can draft and summarize while the real values stay inside the runtime. Restore is role-gated: ordinary HR staff get masked salary and masked contact details back, while the hr_manager role restores them in full.
HRIS / ATS / Personnel File
|
v
OGuardAI Runtime (employee PII exists only here, transiently)
|
+---> Tokenized text (identifiers + salary tokenized) ---> LLM Provider
+---> Encrypted session blob ---------------------------> Your Application
|
v
Restored output (role-gated)
+---> hr_manager: full restore (salary, contact, employee id)
+---> HR staff: masked salary and contact
+---> Redacted: SSN, date of birth, passport, health id (never recoverable)Detected Entity Types
These are the entity types the shipped hr policy governs.
| Entity Type | Examples | Default Action |
|---|---|---|
person ** | Employee and applicant names | Tokenize, full only for hr_manager |
salary * | Annual pay, compensation figures | Tokenize, masked; full only for hr_manager |
employee_id * | Personnel numbers | Tokenize, full only for hr_manager |
email | Work and personal email | Tokenize, full only for hr_manager |
phone | Contact numbers | Tokenize, full only for hr_manager |
address | Home and office addresses | Tokenize |
company | Employer, former employers | Tokenize |
iban | Payroll bank accounts | Tokenize, restore masked |
credit_card | Company card numbers | Tokenize, restore masked |
ssn | National insurance / social security | Redact (never reaches the model) |
date_of_birth | DOB fields | Redact (never reaches the model) |
passport | Passport numbers | Redact (never reaches the model) |
health_id | Health-related identifiers | Redact (never reaches the model) |
Entity types marked with * are custom types defined via
custom_patternsin the policy, not built-in. See the Extending Entities guide for how to add custom types.
Entity types marked with ** are detected by the NER detector sidecar, which requires
detector.modeset tobothoradvanced. The built-in detector alone covers structured PII (email, phone, IBAN, card, identifiers, address, date of birth) but does not detect person, company, or location names. In builtin-only mode employee names are not tokenized and would reach the model, so setdetection.required_for: [person]if you need the request to fail closed rather than pass names through. Treat name protection as a data-minimization control, not an absolute guarantee.
Example Policy
The hr policy ships in policies/hr/policy.yaml. It redacts the high-sensitivity identifiers, tokenizes names and contact details, and gates full restore of salary, names, contact, and personnel numbers behind the hr_manager caller role.
name: "hr"
version: "1.0.0"
description: "Human resources policy: SSN, date of birth, passport, and health id redacted; salary masked for HR staff and full only for the hr_manager role; employee names and contact tokenized, full only for hr_manager."
rules:
- entity_type: "ssn"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "date_of_birth"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "passport"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "health_id"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "iban"
protection_level: 1
action: "tokenize"
restore_mode: "masked"
conditions: []
- entity_type: "credit_card"
protection_level: 1
action: "tokenize"
restore_mode: "masked"
conditions: []
- entity_type: "salary"
protection_level: 2
action: "tokenize"
restore_mode: "masked"
conditions:
- field: "caller_role"
operator: "eq"
value: "hr_manager"
override_restore_mode: "full"
- entity_type: "person"
protection_level: 2
action: "tokenize"
conditions:
- field: "caller_role"
operator: "eq"
value: "hr_manager"
override_restore_mode: "full"
- entity_type: "email"
protection_level: 2
action: "tokenize"
conditions:
- field: "caller_role"
operator: "eq"
value: "hr_manager"
override_restore_mode: "full"
- entity_type: "phone"
protection_level: 2
action: "tokenize"
conditions:
- field: "caller_role"
operator: "eq"
value: "hr_manager"
override_restore_mode: "full"
- entity_type: "address"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "location"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "company"
protection_level: 2
action: "tokenize"
conditions: []
# HR-defined entity (detected by custom_patterns below); full only for hr_manager.
- entity_type: "employee_id"
protection_level: 2
action: "tokenize"
conditions:
- field: "caller_role"
operator: "eq"
value: "hr_manager"
override_restore_mode: "full"
custom_patterns:
- entity_type: "employee_id"
pattern: '\bEMP[-:\s]?\d{4,8}\b'
confidence: 0.9
context_words: ["employee", "emp", "staff", "personnel"]
- entity_type: "salary"
pattern: '\b\d{1,3}(?:[.,]\d{3})+(?:[.,]\d{2})?\b'
confidence: 0.85
context_words: ["salary", "gehalt", "compensation", "annual", "pay", "vergütung"]
defaults:
protection_level: 2
action: "tokenize"
restore_mode: "partial"
on_redact: "continue"
metadata_policy:
expose_gender: true
expose_formality: true
expose_language: true
expose_role: trueThe caller_role condition is the access control: a request that passes context.caller_role: "hr_manager" restores salary, names, contact, and personnel numbers in full; any other caller gets the masked default. Pass the role on the transform request via context.caller_role.
Example API Call
Transform a personnel note
curl -X POST http://localhost:3000/v1/transform \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key-here" \
-d '{
"input": "Employee Jonas Weber (EMP-40218), SSN 078-05-1120, DOB 1990-03-12, annual salary 82.000,00 EUR. Contact: jonas.weber@company.de, +49 89 1234567. Payroll IBAN DE89 3704 0044 0532 0130 00.",
"policy": "hr",
"context": { "caller_role": "hr_staff" }
}'Response (tokenized)
{
"safe_text": "Employee {{person:p_001:ad4f97591c16}} ({{custom:employee_id:x_001:e9c35b18ad9b}}), SSN [REDACTED:ssn], DOB [REDACTED:date_of_birth], annual salary {{custom:salary:x_002:251177a0ba1f}}. Contact: {{email:e_001:1bcaef1a4aff}}, {{phone:ph_001:71453119be53}}. Payroll IBAN {{iban:ib_001:a7a60e9fe667}}.",
"session_id": "01916d5b-8e2f-7000-8000-000000000004",
"session_state": "eyJ2IjoxLCJzaWQiOi...",
"entity_context": [
{ "token": "{{person:p_001:ad4f97591c16}}", "type": "person", "gender": "male", "language": "de" }
],
"stats": { "entities_detected": 8, "entities_transformed": 6, "entities_blocked": 2 }
}The SSN and date of birth are redacted (purged from the session, never recoverable). Name, personnel number, salary, contact details, and IBAN are tokenized. The model can draft the letter or summary from tokens without seeing the real values.
Rehydrate for an HR manager
curl -X POST http://localhost:3000/v1/rehydrate \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key-here" \
-d '{
"output": "<LLM-generated summary with tokens>",
"session_state": "eyJ2IjoxLCJzaWQiOi..."
}'The caller role is bound from the authenticated principal (its API-key scope or JWT claim), not the request body. When the principal carries caller_role: hr_manager, salary, name, contact, and personnel number restore in full. The same session state rehydrated for an hr_staff caller returns masked salary and masked contact, and the redacted SSN, date of birth, passport, and health id stay purged for everyone.
Data Protection Notes
| Requirement | How OGuardAI Addresses It |
|---|---|
| GDPR Art. 5(1)(c) data minimization | Only detected entity types are tokenized or redacted before the prompt leaves the runtime; the high-sensitivity identifiers are redacted outright |
| GDPR Art. 9 special categories | Health identifiers are redacted and never transmitted to the provider |
| Access control (need-to-know) | The caller_role condition restores salary and contact in full only for hr_manager; ordinary HR staff get masked values |
| Works-council (Betriebsrat) agreements | Role-gated restore and PII-free audit events support internal agreements on who may view personnel data through AI-assisted tooling |
| Audit | Every transform and rehydrate emits structured events with entity types and counts, never raw employee data |
OGuardAI is one technical control in a broader HR data-governance program. It reduces the employee PII that reaches an LLM provider for detected entities; it does not, by itself, make an HR AI deployment GDPR-compliant. Confirm your processing basis and any works-council agreement with your data protection officer.
Related Resources
- Finance & PCI-DSS: Role-gated restore and redaction for financial PII
- Policy Authoring Guide: Conditions,
caller_role, and restore modes - Extending Entity Types: How to add custom patterns for personnel numbers and salary
- GDPR Compliance: GDPR-specific compliance documentation
Legal & Compliance
Protect attorney-client privilege and confidential case data when using AI for contract review, legal research, and document summarization
Government & Public Sector
Protect citizen and personnel data at the highest security tier when using AI in public-sector workflows, with fail-closed redaction and masked restore for permitted entities