PII Masking
AgentMark PII masking strips sensitive data from span attributes before traces are exported. Masking runs client-side in your application process, so no unmasked data ever leaves your environment. You can use a custom mask function, the built-in PII masker, environment variable suppression, or any combination of these approaches.How it works
PII masking is implemented as an OpenTelemetrySpanProcessor that wraps the export pipeline. When a span finishes, the masking processor intercepts it before the exporter sends data over the network.
Span finishes
Your application completes an LLM call or tool invocation. The span is ready for export.
MaskingSpanProcessor intercepts
If masking is configured, the processor runs env var suppression first, then your mask function on each sensitive attribute.
- No unmasked data ever leaves your application process. Masking runs in-memory before any network call.
- Zero overhead when masking is disabled. The processor is only added to the pipeline when you configure a
maskfunction or set env vars. - Standard OTel pattern. The
MaskingSpanProcessorwraps your existingBatchSpanProcessororSimpleSpanProcessor— no forking or patching required.
Before and after
WithcreatePiiMasker() enabled, PII tokens like [EMAIL], [SSN], and [PHONE] replace sensitive data in the trace viewer:
![Trace with PII masking enabled — sensitive data replaced with tokens like [EMAIL], [SSN], [PHONE]](https://mintcdn.com/puzzlet-9ba7bb98/5xsP1AqgWmw7fWzd/images/pii-masking/trace-masked.png?fit=max&auto=format&n=5xsP1AqgWmw7fWzd&q=85&s=b2af35f969a957fa2a6a007a5246f15a)
AGENTMARK_HIDE_INPUTS=true, all input attributes show [REDACTED] while outputs remain visible:
![Trace with input suppression — all inputs show [REDACTED]](https://mintcdn.com/puzzlet-9ba7bb98/5xsP1AqgWmw7fWzd/images/pii-masking/trace-redacted.png?fit=max&auto=format&n=5xsP1AqgWmw7fWzd&q=85&s=45f0ddef9e1c12de8c15395a1d421280)
createPiiMasker(email=True, ssn=True):
AGENTMARK_HIDE_INPUTS=true:
gen_ai.request.model and gen_ai.usage.total_tokens are never masked — these operational attributes contain no user data.
Basic usage
Pass amask function to AgentMarkSDK. The function receives each string attribute value and returns the redacted version.
mask function is called on every maskable span attribute before the span is handed to the exporter. The function must be synchronous. You have full control over the replacement logic.
Built-in PII masker
AgentMark ships a built-in PII masker that covers common patterns out of the box. Enable the patterns you need:Built-in patterns
email — Matches email addresses like user@example.com. Replaced with [EMAIL].
phone — Matches phone numbers like (555) 123-4567. Replaced with [PHONE].
ssn — Matches Social Security numbers like 123-45-6789. Replaced with [SSN].
creditCard — Matches credit card numbers like 4111 1111 1111 1111. Replaced with [CREDIT_CARD].
ipAddress — Matches IP addresses like 192.168.1.100. Replaced with [IP_ADDRESS].
All patterns default to false. Only patterns you explicitly enable are applied.
Custom patterns
You can add custom patterns alongside the built-in ones. Each entry needs a regex pattern and a replacement string.Environment variable suppression
For a zero-code option, set environment variables to suppress all inputs, all outputs, or both:[REDACTED]. No code changes are needed.
If both environment variable suppression and a
mask function are configured, suppression runs first. The mask function then receives the already-suppressed values.Masked attributes reference
AgentMark masks specific span attributes depending on their category. Input attributes (suppressed byAGENTMARK_HIDE_INPUTS):
gen_ai.request.input— The prompt or messages sent to the modelgen_ai.request.tool_calls— Tool call arguments included in the request
AGENTMARK_HIDE_OUTPUTS):
gen_ai.response.output— The model’s text responsegen_ai.response.output_object— Structured output from the model
agentmark.metadata.*— Custom metadata attached to spans
Error handling
PII masking uses fail-closed behavior. If yourmask function throws an error, the span is dropped entirely and never exported. This ensures that unmasked data is never sent to the trace backend.
Tracing continues normally for subsequent spans after a mask failure. The dropped span does not affect the rest of the trace pipeline.
Recipes
Microsoft Presidio (Python)
Microsoft Presidio uses NLP to detect unstructured PII like person names, addresses, and passport numbers that regex patterns miss. Since Presidio is a Python library, this recipe applies to the Python SDK.Python
PERSON, LOCATION, US_PASSPORT, IBAN_CODE, and CRYPTO. See the Presidio supported entities for the full list.
Healthcare (HIPAA)
Combine built-in patterns with custom patterns for Protected Health Information:Python
Financial services
For PCI-DSS compliance, enable credit card masking and add patterns for financial identifiers:TypeScript
For maximum compliance assurance, combine a
mask function with AGENTMARK_HIDE_INPUTS=true as a defense-in-depth strategy. The env var acts as a safety net in case a new input attribute is added that the mask function doesn’t cover.Have Questions?
We’re here to help! Choose the best way to reach us:
- Email us at hello@agentmark.co for support
- Schedule an Enterprise Demo to learn about our business solutions