PIIRedactor is an Intercept middleware for Laravel AI SDK agents. It detects and handles sensitive personal or secret-like data before an agent prompt reaches the AI provider.
It can redact, mask, log, block, or delegate handling to a custom callback.
Installation
Install the package with Composer:Basic usage
Return thePIIRedactor middleware on an agent’s middleware method.
- use the
redactaction - detect emails, phone numbers, credit cards, IP addresses, MAC addresses, URLs, API keys, and bearer tokens
- block credit cards, API keys, and bearer tokens
- redact lower-risk values such as emails, phone numbers, MAC addresses, URLs, and IP addresses
- not log raw detected values
- not log prompt previews
Supported actions
The recommended default action is
redact.
Some entities can still be blocked even when the action is redact. By default, credit cards, API keys, and bearer tokens are blocked.
Supported entities
Names, addresses, passports, national insurance numbers, and medical identifiers are not included in the current version. These values are harder to detect safely with regex alone and can create false positives.
Configuration
No configuration is required. The middleware works out of the box using safe internal defaults. The defaults may be overridden via the constructor or via the sharedconfig/intercept.php file, published with:
Configuration priority
Configuration is resolved in this order: That means constructor values always win over published config values. For example, if your config says:log for that agent, even though the global config says redact.
Partial configuration
You do not need to define every option inconfig/intercept.php.
This is valid:
Usage examples
Redacting PII
Useredact when you want to remove detected values while preserving the rest of the user request.
Email victor@example.com about this ticket.
Email [EMAIL_1] about this ticket.
Masking PII
Usemask when the model needs a rough hint of the value format but should not see the full value.
Email victor@example.com about this ticket.
Email v*****@example.com about this ticket.
Logging detections
Uselog when you want to observe real traffic before redacting or blocking.
Blocking PII
Useblock when the prompt should stop as soon as supported PII is detected.
PIIRedactorException.
Blocked entities
Some entities are treated as high-risk and are blocked by default, even when the action isredact.
Default blocked entities:
Detecting selected entities
You can limit detection to specific entity types.Allowing specific email addresses
UseallowedEmails when known safe email addresses should not be redacted or blocked.
Email support@example.com about this ticket.
Allowing email domains
UseallowedDomains when all email addresses from a trusted domain should be ignored.
Custom replacement format
The default redaction format is:Custom mask character
The default mask character is*.
Custom callback handling
Use a callback when you want full control over the response. The callback receives:Tool approval resumes
When an agent pauses for tool approval, the run is resumed by passingDecisions back to the agent instead of a new prompt.
A resumed prompt carries no prompt text. The only new content is what a human supplied while resolving the pending tool calls:
- edited tool arguments, from
Decision::edit() - rejection results, from
Decision::reject()
Actions on a resumed run
A paused turn must replay verbatim against the provider that recorded it, so the Laravel AI SDK makes resumed prompts immutable.redact and mask have nowhere to write their output, so they degrade to logging.
Blocked entities still stop the run regardless of the configured action. A credit card, API key, or bearer token in an edited tool argument is refused exactly as it would be in a prompt.
Reading the logs
Detections found in approval decisions are logged under a distinct message,PII detected in tool approval decisions., with a source of approval_decisions:
degraded_from key appears only when the run continued despite a configured action that could not be applied. A blocked run never reports it.
The field value is a dot path into the edited arguments, so nested values are reported precisely, for example arguments.filters.contact.email.
Disabling approval decision scanning
Scanning is enabled by default. To disable it globally:Production rollout
A practical rollout path:Security notes
Use this middleware as one layer in a broader AI safety and privacy strategy. Recommended additional controls:- avoid sending secrets to AI providers
- minimise prompt context
- keep system instructions separate from user input
- limit tool permissions
- validate tool arguments
- redact sensitive data before tool calls where appropriate
- log detections safely
- avoid prompt previews in production logs
- review false positives before blocking aggressively
- use provider-level safety and privacy controls where available
Detection limitations
This middleware is regex-based and intentionally focused on structured values. It can miss:- names
- free-form addresses
- uncommon phone formats
- unusual API key formats
- identifiers without clear patterns
- sensitive context that does not look like structured PII
When to use each action
Useredact when you want to remove detected values while preserving the rest of the user request.
Use mask when the model needs a rough hint of the value format but should not see the full value.
Use log when you are tuning detection, observing real traffic, or rolling out gradually.
Use block when sensitive data should never reach the provider.
Use blockEntities when only specific high-risk entities should stop the prompt, even if the general action is redact, mask, or log.
Use a callback when your application needs custom behaviour such as audit logging, custom exceptions, approval flows, or user-facing fallback responses.