Column Masking and PII Protection for AI Workloads
When an agent reads from a table, the whole row flows into the model's context: the email, the phone number, the card's last four, the home address. Most of the time, none of that is what the agent needs. It needs to count, group, join, and analyze. The raw PII is along for the ride, and now it is in a prompt, possibly in a log, possibly in a third party's training pipeline.
Column masking cuts that off. PgBeam transforms sensitive columns in flight, by schema.table.column, before the result leaves the proxy. Your application reads real values. The agent receives masked ones.
Three transforms
You choose, per column, how a value is masked:
- Redact: replace the value with a fixed token, like
***. The agent knows a value exists but never sees it. - Null: return
NULL. Useful when the column should simply be absent for this credential. - Hash: replace the value with a stable hash. The same input always produces the same output, so the agent can still
GROUP BYit,JOINon it, and count distinct values, without ever seeing the original.
The hash transform is the one that makes masking useful for analysis rather than just suppression. An agent can answer "how many distinct customers placed more than three orders" against a hashed email column. The grouping works because identical emails hash identically. The privacy holds because the agent cannot reverse the hash back to an address.
Why this matters more for agents
A human analyst who sees a raw email reads it and moves on. An agent does something worse with it: it puts the value into a context window, which may be logged by the model provider, retained, or fed into evaluation and training systems you do not control. The PII does not just get seen. It gets copied into systems outside your boundary.
Masking at the wire means the raw value never enters that pipeline. The model cannot leak what it never received. This is the difference between "we told the agent not to log PII" and "the PII was redacted before the agent could see it." Only the second one survives an audit.
In flight, not at rest
Masking happens on the result stream as it passes through the proxy. Nothing in the database changes. There is no separate masked copy of the table to maintain, no ETL job, no view to keep in sync. The same row is served raw to your application's credential and masked to the agent's credential, decided by policy at read time.
app credential → email = "ada@example.com"
agent credential → email = "8f1c…" (hashed) or "***" or NULLComposes with the rest
Masking is one layer. It pairs naturally with the others:
- Read-only enforcement so the agent cannot write the unmasked value back.
- Table and column allowlists so the column is only reachable if you allowed it at all.
- Row-level policies so the agent only sees its slice of rows, masked.
- The audit log, which records that a masking transform was applied, so you can prove the agent never received the raw value.
The goal is simple to state: let the agent be useful on the shape of your data without ever handing it the sensitive contents. Masking is how you keep the analysis and drop the exposure.
Try PgBeam or see the full feature set.