Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions docs/changelog.mdx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
---
title: "Changelog"
description: "Product updates and release notes for Intercept, including dependency limits, security patches, and changes to Tool Approval Guard defaults."
sidebarTitle: "Changelog"
rss: true
description: "Product updates and release notes for Intercept, including dependency limits, security patches, and changes to middleware collection."
---

Product updates and release notes for Intercept.

<Update label="September 27, 2026" description="v1.0.0" tags={["Major", "Breaking"]}>
Supports `laravel/ai` v1.0. The SDK now runs agent middleware once per generation step, not once per prompt.

Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Configuration"
description: "Publish config/intercept.php, learn configuration priority, and set global or per-agent options for Injection Guard, PII Redactor, and Tool Approval Guard."
description: "Publish config/intercept.php, learn configuration priority, and set global or per-agent options for middleware collection."
sidebarTitle: "Configuration"
---

Expand Down
6 changes: 3 additions & 3 deletions docs/contributor-resources/support.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
title: "Support utilities"
description: "Learn how the intercept-support package provides the shared config file, the InterceptConfig helper, and the service provider used by Intercept middleware."
sidebarTitle: "Support utilities"
---

`promptphp/intercept-support` provides shared support utilities and configuration for the Intercept middleware ecosystem.

Most users do not need to install or use this package directly. Composer installs it automatically when an Intercept middleware package requires it.
Users do not need to install or use this package directly. Composer installs it automatically when an Intercept middleware package requires it.

The support package provides shared infrastructure used across Intercept packages, including:

- the shared `config/intercept.php` configuration file
- the `intercept-config` publish tag
- the `InterceptConfig` helper for resolving middleware configuration

- the `InterceptServiceProvider` for Laravel package registration
- the Intercept base exception class

## Installation

Expand Down
1 change: 0 additions & 1 deletion docs/middleware/injection-guard.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
title: "Injection Guard"
description: "Install and configure PromptInjectionGuard to detect prompt injection in Laravel AI SDK agents, then block, log, warn, sanitize, or run a custom callback."
sidebarTitle: "Injection Guard"
---

Expand Down
72 changes: 29 additions & 43 deletions docs/middleware/pii-redactor.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
title: "PII Redactor"
description: "Use PIIRedactor to detect emails, phone numbers, credit cards, and secret-like data in Laravel AI agent prompts, then redact, mask, log, or block them."
sidebarTitle: "PII Redactor"
---

Expand All @@ -21,7 +20,7 @@ composer require promptphp/intercept-pii-redactor
```

<Tip>
If you prefer to install the main Intercept package to get the full middleware collection, run:
If you prefer to install the main intercept package to get the full middleware collection, run:
</Tip>

```bash
Expand Down Expand Up @@ -76,7 +75,7 @@ By default, the middleware will:

The recommended default action is `redact`.

Some entities can still be blocked even when the action is `redact`. By default, the middleware blocks credit cards, API keys, and bearer tokens.
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

Expand All @@ -97,7 +96,7 @@ Names, addresses, passports, national insurance numbers, and medical identifiers

No configuration is required. The middleware works out of the box using safe internal defaults.

You can override the defaults via the constructor or via the shared `config/intercept.php` file. Publish it with:
The defaults may be overridden via the constructor or via the shared `config/intercept.php` file, published with:

```bash
php artisan vendor:publish --tag=intercept-config
Expand All @@ -107,7 +106,7 @@ Explore the [configuration guide](/configuration) for more details on how to con

### Configuration priority

Intercept resolves configuration in this order:
Configuration is resolved in this order:

```mermaid placement="top-right"
flowchart LR
Expand Down Expand Up @@ -263,10 +262,10 @@ public function middleware(): array
}
```

If the middleware detects PII, it throws a `PIIRedactorException`.
If PII is detected, the middleware throws a `PIIRedactorException`.

<Tip>
You can also catch `InterceptException`, the parent exception class that all Intercept middleware throw.
You may also catch the parent exception class `InterceptException` throwable by all Intercept middleware.
</Tip>

```php
Expand All @@ -283,7 +282,7 @@ try {

### Blocked entities

The middleware treats some entities as high-risk and blocks them by default, even when the action is `redact`.
Some entities are treated as high-risk and are blocked by default, even when the action is `redact`.

Default blocked entities:

Expand All @@ -295,7 +294,7 @@ Default blocked entities:
]
```

This means the middleware blocks a prompt containing a supported API key or bearer token by default.
This means a prompt containing a supported API key or bearer token will be blocked by default.

You can override blocked entities:

Expand Down Expand Up @@ -429,64 +428,51 @@ Use a callback when you want full control over the response.
The callback receives:

```php
PendingStep $step
AgentPrompt $prompt
Closure $next
RedactionResult $result
```

Return what `$next` returns. Example:
Example:

```php
use Laravel\Ai\PendingStep;

public function middleware(): array
{
return [
new PIIRedactor(
callback: function (PendingStep $step, Closure $next, $result) {
if ($step->isFirstStep()) {
logger()->warning('Sensitive data detected in AI prompt.', [
'model' => $step->model,
'entities' => array_map(
fn ($detection) => $detection->type,
$result->detections,
),
]);
}

return $next($step->withInstructions(
$step->instructions.PHP_EOL.'Treat the user input as sensitive data.'
));
callback: function ($prompt, $next, $result) {
logger()->warning('Sensitive data detected in AI prompt.', [
'agent' => $prompt->agent::class,
'entities' => array_map(
fn ($detection) => $detection->type,
$result->detections,
),
'prompt_hash' => hash('sha256', $prompt->prompt),
]);

return $next(
$prompt->prepend(
'Privacy notice: Treat the following user input as sensitive data.'
)
);
},
),
];
}
```

When you provide a callback, it takes priority over the configured action.

The callback runs on every step whose newest user message carries PII. Check `$step->isFirstStep()` to act once per run. On a resumed run, the callback receives the `AgentPrompt`, a `null` in place of `$next`, and the result. The return value is ignored there, so throw to stop the run.

## Generation steps

The Laravel AI SDK runs agent middleware once for each generation step. A run that calls tools has several steps. The prompt is the newest user message in `$step->messages`.

A change to the step history applies to that step only. The middleware therefore redacts or masks every user message in the history on every step. This includes earlier turns that the SDK replays from a conversation store. It logs and blocks once, on the step that starts the turn.

<Warning>
The SDK stores the original prompt in the conversation store, and it builds the conversation title from that prompt. Middleware cannot change either. Redaction keeps PII away from the AI provider, not away from your conversation tables.
</Warning>
When a callback is provided, it takes priority over the configured action.

## Tool approval resumes

When an agent pauses for tool approval, you resume the run by passing `Decisions` back to the agent instead of a new prompt.
When an agent pauses for tool approval, the run is resumed by passing `Decisions` 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()`

Both reach the AI provider, and the SDK applies them before the first step of the resumed run. Intercept therefore scans them from a listener on the SDK prompt event, before any approved or edited tool call executes. It uses the same detectors, Luhn validation, and email allowlists it applies to a prompt.
Both reach the AI provider, so this middleware scans them using the same detectors, Luhn validation, and email allowlists it applies to a prompt.

```php
use Laravel\Ai\Approvals\Decision;
Expand Down Expand Up @@ -561,7 +547,7 @@ public function middleware(): array
```

<Warning>
Detection offsets on this path are relative to the decision value the detection was found in, not to the prompt. Offsets exist to drive redaction, which cannot apply to a resumed run. Custom callbacks should use the detection `type` and `value` rather than `start` and `length`.
Detection offsets on this path are relative to the decision value the detection was found in, not to the prompt. Offsets exist to drive redaction, which cannot be applied to a resumed run, so custom callbacks should use the detection `type` and `value` rather than `start` and `length`.
</Warning>

## Production rollout
Expand Down
Loading