Healthcare & HIPAA
Protect PHI when using AI for clinical notes, patient summaries, and medical Q&A while supporting your HIPAA compliance program without sacrificing AI quality
Protect patient health information (PHI) when using AI for clinical notes, patient summaries, and medical question answering, while supporting your HIPAA compliance program.
The Problem
Healthcare organizations face a regulatory wall when adopting AI. Clinical workflows generate enormous volumes of text, intake forms, discharge summaries, referral letters, insurance pre-authorizations, that benefit from AI-assisted drafting, summarization, and coding. But every document contains protected health information: patient names, medical record numbers, health plan IDs, dates of birth, addresses, and phone numbers.
HIPAA's Security Rule and Privacy Rule impose strict requirements on how PHI is handled. Sending raw PHI to a third-party LLM provider creates a compliance gap that most organizations cannot close with a Business Associate Agreement alone. The risk calculus is straightforward: a single breach involving PHI triggers mandatory notification, OCR investigation, and potential penalties of up to $2.1 million per violation category per year.
The alternatives are worse. On-premise models are expensive to operate and lag behind commercial models in quality. Manual redaction is slow and error-prone. Regex stripping destroys clinical context: removing all names from a multi-patient summary makes the output unusable.
How OGuardAI Solves It
OGuardAI sits between your clinical application and the AI model. PHI is detected, replaced with semantic tokens that carry safe metadata, and the tokenized text is sent to the LLM. The model works from tokens rather than the real identifiers, and retains enough context (gender, language, and the provider role) to generate clinically useful output. After the model responds, OGuardAI restores the original values based on the output channel's policy.
EHR / Clinical App
|
v
OGuardAI Runtime (PHI exists only here, transiently)
|
+---> Tokenized text (detected PHI tokenized) ---> LLM Provider
+---> Encrypted session blob ----> Your Application
|
v
Restored output (channel-specific)
+---> Physician review: full restore
+---> Patient portal: masked identifiers
+---> Audit log: no real valuesDetected Entity Types
These are the entity types the shipped healthcare-hipaa template governs.
| Entity Type | Examples | Default Action |
|---|---|---|
person ** | Patient names, provider names | Tokenize with gender/language metadata |
health_id | Health plan IDs | Redact (never reaches the model) |
date_of_birth | DOB fields, ages | Tokenize, restore masked |
ssn | Social Security numbers | Redact (never reaches the model) |
passport | Passport numbers | Redact (never reaches the model) |
address | Street addresses, ZIP codes | Tokenize |
phone | Phone and fax numbers | Tokenize |
email | Patient and provider email addresses | Tokenize |
mrn * | Medical record numbers | Tokenize, restore masked |
npi * | National Provider Identifiers | Tokenize |
dea * | DEA prescriber numbers | Redact (never reaches the model) |
diagnosis ** | Medical conditions | Tokenize, restore masked |
medication ** | Drug names | Tokenize, restore masked |
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.diagnosisandmedicationare semantic PHI that regex cannot catch: the template asks the sidecar for the NER labelsmedical conditionandmedicationand maps them to these types. Because they are declared underdetection.required_for,healthcare-hipaafails closed: if the NER sidecar is unavailable, the request is rejected rather than silently downgraded to builtin-only. Note the honest scope: a GLiNER span below the confidence threshold is not returned by the detector and therefore cannot be protected, so treat this as a data-minimization control, not an absolute guarantee.
Example Policy
healthcare-hipaa ships as an opt-in template under policies/templates/: it declares required_for: [diagnosis, medication], so it requires the NER detector and fails closed, and is not auto-loaded. Copy it into your active policy directory and run detector.mode: both or advanced to enable it.
name: "healthcare-hipaa"
version: "1.0.0"
description: "HIPAA-aligned healthcare policy: redacts PHI identifiers, tokenizes clinical names"
rules:
- entity_type: "ssn"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "health_id"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "passport"
protection_level: 1
action: "redact"
conditions: []
- entity_type: "date_of_birth"
protection_level: 2
action: "tokenize"
restore_mode: "masked"
conditions: []
- entity_type: "person"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "email"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "phone"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "address"
protection_level: 2
action: "tokenize"
conditions: []
# Hospital-defined PHI entities (detected by custom_patterns below).
- entity_type: "mrn"
protection_level: 1
action: "tokenize"
restore_mode: "masked"
conditions: []
- entity_type: "npi"
protection_level: 2
action: "tokenize"
conditions: []
- entity_type: "dea"
protection_level: 1
action: "redact"
conditions: []
# Semantic PHI caught by the per-policy NER labels declared in the detection section below.
- entity_type: "diagnosis"
protection_level: 1
action: "tokenize"
restore_mode: "masked"
conditions: []
- entity_type: "medication"
protection_level: 1
action: "tokenize"
restore_mode: "masked"
conditions: []
# Domain entities a hospital defines without any code change. Each becomes
# {{custom:<type>:id}} and is governed by the matching rule above.
custom_patterns:
- entity_type: "mrn"
pattern: '\bMRN[-:\s]?\d{6,10}\b'
confidence: 0.9
context_words: ["mrn", "medical record", "patient", "chart"]
- entity_type: "npi"
pattern: '\bNPI[-:\s]?\d{10}\b'
confidence: 0.9
context_words: ["npi", "provider", "physician"]
- entity_type: "dea"
pattern: '\b[A-Z]{2}\d{7}\b'
confidence: 0.85
context_words: ["dea", "prescriber", "controlled"]
# Per-policy semantic NER labels: ask the detector for diagnoses and medications,
# which regex cannot catch. Additive (built-in person/location detection is
# unaffected) and only requested when the NER sidecar is configured. Listing them
# under required_for makes the policy fail closed when the sidecar is unavailable.
detection:
ner_labels:
- "medical condition"
- "medication"
ner_label_map:
"medical condition": "diagnosis"
"medication": "medication"
required_for:
- "diagnosis"
- "medication"
# Policy-defined roles: label a detected person as the patient or doctor from
# nearby context. The role is one of these declared names, never the raw value.
roles:
- name: "patient"
applies_to: ["person"]
priority: 100
context_words: ["patient", "Patientin", "admitted", "diagnosed with", "presented with"]
anchored_regex:
- '(?i)\bpatient(?:in)?\b[^.\n]{0,40}\{\{ENTITY\}\}'
- name: "doctor"
applies_to: ["person"]
priority: 90
context_words: ["Dr.", "doctor", "physician", "attending", "Arzt", "Ärztin"]
anchored_regex:
- '(?i)\b(?:dr\.?|doctor|physician|arzt|ärztin)\s+\{\{ENTITY\}\}'
defaults:
protection_level: 2
action: "tokenize"
restore_mode: "full"
on_redact: "continue"
metadata_policy:
expose_gender: true
expose_formality: false
expose_language: true
expose_role: trueThe template has no channel_rules: its default restore_mode: full restores every non-redacted entity, and redacted types (ssn, health_id, passport, dea) are purged and never recoverable. Add channel_rules (as in the finance and legal policies) if you need a patient-portal or log-safe channel that masks or drops identifiers.
Example API Call
Transform a clinical note
Policy availability:
healthcare-hipaais an opt-in template underpolicies/templates/; copy it into your active policy directory first (see above). For a ready-to-run clinical policy that needs no copy-in, use the shipped, auto-loadedhealthcare-clinical, which adds German clinical identifiers (KVNR under section 203 StGB, ICD-10) and role-gated restore (clinician and nurse full, coder partial, researcher abstract).
curl -X POST http://localhost:3000/v1/transform \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key-here" \
-d '{
"input": "Patient: Sarah Chen, MRN: MRN-0048271, DOB: 06/14/1978. Presenting with persistent lower back pain radiating to left leg for 3 weeks. Previous lumbar MRI (2024) reviewed. Contact: (415) 555-0193, sarah.chen@email.com. Referring provider NPI 1730154321.",
"policy": "healthcare-hipaa"
}'Response (tokenized)
{
"safe_text": "Patient: {{person:p_001:ad4f97591c16}}, MRN: {{custom:mrn:x_001:42f5f25fb8cc}}, DOB: {{date_of_birth:dob_001:674de46dbb79}}. Presenting with persistent lower back pain radiating to left leg for 3 weeks. Previous lumbar MRI (2024) reviewed. Contact: {{phone:ph_001:71453119be53}}, {{email:e_001:1bcaef1a4aff}}. Referring provider NPI {{custom:npi:x_002:18c3bb90e9ad}}.",
"session_id": "01916a3e-7b2c-7000-8000-000000000001",
"session_state": "eyJ2IjoxLCJzaWQiOi...",
"entity_context": [
{ "token": "{{person:p_001:ad4f97591c16}}", "type": "person", "gender": "female", "language": "en", "role": "patient" },
{ "token": "{{date_of_birth:dob_001:674de46dbb79}}", "type": "date_of_birth" }
],
"stats": { "entities_detected": 6, "entities_transformed": 6, "entities_blocked": 0 }
}Symptoms and imaging history pass through as free text. When the NER sidecar is enabled, named diagnoses and medications are additionally tokenized (restored masked), so the LLM receives enough context to draft a useful clinical summary without ever seeing the patient's real name, MRN, or contact information.
Rehydrate for the physician
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...",
"output_channel": "internal_summary"
}'With the template's default restore_mode: full, the physician sees the summary with names, phone, email, and NPI restored, while date_of_birth and mrn come back masked (their per-rule restore_mode: masked) and the redacted ssn/health_id/passport/dea values stay purged. To serve a patient portal with masked identifiers or a log channel that drops PHI entirely, add a channel_rules block and pass its channel name as output_channel.
HIPAA Compliance Notes
| HIPAA Requirement | How OGuardAI Addresses It |
|---|---|
| Minimum Necessary (164.502(b)) | Policy engine enforces entity-level data minimization -- only the entity types needed for the AI task are tokenized; the rest are blocked |
| Access Controls (164.312(a)) | Output channels enforce role-based restore modes -- physicians see full data, patients see masked data, logs see nothing |
| Encryption (164.312(a)(2)(iv)) | Session state is AES-256-GCM encrypted; PHI exists only transiently in RAM during processing |
| Audit Controls (164.312(b)) | Every transform and rehydrate operation emits structured audit events with entity types and counts -- never raw PHI |
| Transmission Security (164.312(e)) | Detected PHI is tokenized before it crosses the trust boundary; only tokenized text is transmitted to the provider |
| BAA Scope | Because detected PHI is tokenized before it reaches the LLM provider, the PHI that provider processes is reduced, which can narrow the BAA scope. It does not remove the need for a BAA. |
OGuardAI does not replace a comprehensive HIPAA compliance program. It is one technical control within the Covered Entity's broader administrative, physical, and technical safeguard framework. Consult your compliance officer and legal counsel for your specific deployment.
Related Resources
- Healthcare Case Study: Step-by-step walkthrough of a patient intake workflow
- GDPR Compliance: GDPR-specific compliance documentation
- Compliance Controls Mapping: HIPAA, GDPR, SOC 2, PCI DSS article-by-article mapping
- Policy Authoring Guide: How to write and customize policies