Most teams handling medical text with GPT-5 or Claude seem to make the same two mistakes:
- Send raw clinical notes to a cloud model and call it a day
- Redact so aggressively that the model can’t reason about the note anymore
Both are bad.
The pattern that actually makes sense for agent workflows is usually consistent, reversible pseudonymization.
Instead of this:
John Smith visited on 2024-01-12 and spoke with Dr. Patel.
or this:
[NAME] visited on [DATE] and spoke with [NAME].
use this:
[PATIENT_NAME_1] visited on [VISIT_DATE_1] and spoke with [CLINICIAN_NAME_1].
That tiny change preserves the structure GPT-5, Claude, and downstream agents actually need.
If you’re building automations in n8n, OpenClaw, Make, Zapier, or a custom OpenAI-compatible stack, this matters a lot more than people think.
The real problem with classic redaction
Blunt redaction protects strings, but it often destroys relationships.
A clinical note is full of references the model needs to keep straight:
- who the patient is
- which clinician said what
- whether the same person appears multiple times
- whether two dates refer to the same event
- whether an identifier repeats consistently across the note
If every person becomes [NAME] and every date becomes [DATE], the model loses co-reference.
That breaks a bunch of very normal workflows:
- summarization
- extraction
- coding assistance
- triage
- routing
- downstream agent handoffs
Here’s the difference.
Bad redaction
[NAME] was admitted on [DATE]. [NAME] reported chest pain. [NAME] discussed family history with [NAME].
Who is who? The patient? A parent? The cardiologist? No idea.
Better pseudonymization
[PATIENT_NAME_1] was admitted on [ADMISSION_DATE_1]. [PATIENT_NAME_1] reported chest pain. [PATIENT_NAME_1] discussed family history with [CLINICIAN_NAME_1].
Now GPT-5 can still follow the story.
That’s the whole point.
The Reddit thread that made this click for me
I found a thread on r/openclaw about an OpenClaw skill called Redacta:
https://reddit.com/r/openclaw/comments/1vidd43/i_built_an_openclaw_skill_that_pseudonymises/
The key idea was simple:
instead of simply deleting information: John Smith → [NAME] you can preserve useful context: John Smith → PERSON_001
That sounds minor.
It isn’t.
That is the difference between a note that still works for an LLM and one that turns into static.
What good pseudonymization looks like
The practical pattern is:
- detect identifiers locally
- replace them with stable typed tokens
- keep the mapping table separate
- send only pseudonymized text to the model
- re-identify only if needed, and as late as possible
For example:
{
"original": "Jane Doe, DOB 1982-04-16, MRN 123456, seen by Dr. Singh on 2025-02-01",
"pseudonymized": "[PATIENT_NAME_1], DOB [DATE_OF_BIRTH_1], MRN [MRN_1], seen by [CLINICIAN_NAME_1] on [VISIT_DATE_1]"
}
And then locally:
{
"[PATIENT_NAME_1]": "Jane Doe",
"[DATE_OF_BIRTH_1]": "1982-04-16",
"[MRN_1]": "123456",
"[CLINICIAN_NAME_1]": "Dr. Singh",
"[VISIT_DATE_1]": "2025-02-01"
}
That local token map is the important part.
It lets agents reason over the note without exposing raw identifiers upstream.
Why stable tokens beat generic placeholders
Stable tokens do three useful things.
1. They preserve co-reference
[PATIENT_NAME_1] in line 3 is the same [PATIENT_NAME_1] in line 40.
2. They preserve role information
[PATIENT_NAME_1] and [CLINICIAN_NAME_1] are not interchangeable.
3. They preserve downstream usability
Your extraction agent, summarizer, coding workflow, or human review queue can still make sense of the note.
For agent pipelines, this is a huge difference.
Regex alone won’t solve this
A lot of engineers start here:
import re
text = re.sub(r"\b\d{3}-\d{2}-\d{4}\b", "[SSN]", text)
text = re.sub(r"\b\d{10}\b", "[PHONE]", text)
That’s fine for fixed patterns.
It is not enough for the whole problem.
Regex is decent for:
- SSNs
- NHS numbers
- MRNs
- phone numbers
- emails
- dates of birth
- ZIP codes or postcodes
Regex is bad at:
- distinguishing patient names from clinician names
- relatives and carers
- free-text addresses
- indirect age references
- contextual identifiers like profession or location
The realistic architecture is a two-layer pipeline.
A sane architecture: deterministic first, model second
Layer 1: local deterministic matching
Use pattern matching for the obvious stuff.
- NHS numbers
- National Insurance numbers
- MRNs
- SSNs
- DOBs
- phone numbers
- emails
- postcodes
Layer 2: contextual entity detection
Use a local model or tightly controlled service for ambiguous entities.
- patient vs clinician names
- relatives
- carers
- professions
- free-text addresses
- indirect identifiers
Then replace everything with stable typed tokens.
That split is just honest engineering.
Pseudonymization is not the same as de-identification
This is where teams get sloppy.
If you can reverse the mapping, the data may still be regulated.
So no, pseudonymization is not magic.
If you keep a token map, you still need to:
- protect it
- control access
- audit usage
- define where re-identification is allowed
- think about whether reversible mapping is even acceptable for the use case
Sometimes reversible pseudonyms are correct.
Sometimes you need one-way tokenization or stricter de-identification.
Google Sensitive Data Protection is pretty clear on this distinction. It supports:
- AES-SIV deterministic encryption
- FPE-FFX format-preserving encryption
- HMAC-SHA-256 hashing
That’s useful because it frames the problem correctly: reduce exposure without destroying utility.
The trap on the other side: preserving too much
You can pseudonymize a note and still leak identity.
If the note keeps:
- a rare profession
- a tiny town
- an unusual diagnosis date
- a very specific age
- a distinctive clinical event
then the note may still be identifiable.
So “we removed names” is not enough.
Sometimes you need a stricter pass.
Sometimes you need Safe Harbor-style removal.
Sometimes you need a human review step.
AWS Comprehend Medical’s PHI categories are a good reminder that privacy is broader than names. It includes things like:
- age
- date
- name
- phone or fax
- ID
- URL
- address
- profession
That’s closer to the real problem.
Tools I’d actually consider
If I were building a gateway in front of GPT-5, Claude, Grok, Qwen, or Llama for internal workflows, I’d look at these:
| Option | What it’s best at |
|---|---|
| Redacta | Clinical pseudonymization with stable labeled tokens, local-first workflows, and local re-identification |
| Microsoft Presidio | General-purpose PII detection and anonymization with strong building blocks for custom services |
| Google Sensitive Data Protection | Managed pseudonymization and tokenization with enterprise-friendly cryptographic primitives |
My opinionated take:
- Redacta is the most interesting if the text is actually clinical
- Microsoft Presidio is the best starting point if you want to build your own service
- Google Sensitive Data Protection is strong if you want managed tokenization primitives and enterprise controls
Quick Presidio example
Presidio is practical because you can run it as libraries or HTTP services.
The docs show an anonymization endpoint like this:
curl -XPOST http://localhost:3000/anonymize \
-H "Content-Type: application/json" \
-d '{
"text":"hello world, my name is Jane Doe. My number is: 034453334",
"anonymizers":{
"PHONE_NUMBER":{
"type":"mask",
"masking_char":"*",
"chars_to_mask":4,
"from_end":true
}
},
"analyzer_results":[
{
"start":24,
"end":32,
"score":0.8,
"entity_type":"NAME"
}
]
}'
That’s not a full clinical pseudonymization pipeline, but it’s a useful foundation.
Quick Redacta example
If you’re already working in OpenClaw-style automation environments:
openclaw skills install redacta
npx -y redacta-mcp
That packaging is better than I expected.
The project is described as shipping across multiple surfaces, including:
- OpenClaw skill
- MCP server
- TypeScript library
- Python library
- CLI
That matters because developers don’t want privacy tooling trapped in one UI.
What a production pipeline should look like
If I were implementing this for a real automation stack, I’d do something like this:
1. Detect obvious identifiers locally
Use deterministic matching for MRNs, NHS numbers, SSNs, DOBs, emails, phone numbers, and postcodes.
2. Run contextual detection in a tightly controlled layer
Separate patient names from clinician names, relatives, carers, and ambiguous references.
3. Replace with stable typed tokens
Use:
[PATIENT_NAME_1]
[CLINICIAN_NAME_1]
[DOB_1]
[MRN_1]
[VISIT_DATE_1]
Not:
[NAME]
[DATE]
4. Store the mapping table separately
Keep it local. Lock it down. Audit it.
5. Send only pseudonymized notes to the model
That can be GPT-5, Claude, or any OpenAI-compatible endpoint.
6. Re-identify only at the end
Do it only if needed, and inside the smallest controlled scope possible.
Why this matters even more for agent workflows
This problem gets worse when you move from one-off prompts to always-on automations.
A real pipeline might be:
local detection -> pseudonymization -> GPT-5 extraction -> n8n routing -> human review -> controlled re-identification
That’s how teams actually build systems.
Not:
paste note into chatbot
And once you accept that, economics matter too.
Because now you’re not paying for one prompt. You’re paying for a workflow with multiple passes:
- detection
- pseudonymization
- extraction
- validation
- summarization
- routing
- maybe a second review pass
That’s where flat-rate compute gets interesting.
If your stack uses an OpenAI-compatible endpoint, Standard Compute is relevant here because it lets teams run multi-step agent flows without per-token billing anxiety. That matters when safety steps stop being optional and become part of the default pipeline.
For n8n, Make, Zapier, OpenClaw, and custom automations, that changes behavior. Teams are less likely to cut corners when every extra pass doesn’t feel like another billing event.
My practical recommendation
If you’re building LLM workflows around medical notes, don’t choose between these two bad options:
- raw-note prompting
- context-destroying redaction
Use consistent pseudonymization first.
Then decide where you need stricter de-identification.
That’s the middle path that actually works.
It preserves enough structure for GPT-5 or Claude to reason correctly, while reducing exposure enough to build a sane pipeline.
For developers, the takeaway is simple:
privacy and utility are not enemies
bad implementations of both are
If your agents need to understand the note, give them structure.
Just don’t give them the patient’s identity unless they truly need it.
Top comments (0)