Integration
Privacy Proxy
`privacy-proxy` is a runtime privacy protection plugin for OpenClaw.
Configuration Example
"messagePlaceholderPolicy": "restore"
README
# Privacy Proxy
English | [ç®€ä½“ä¸æ–‡](./README.zh-CN.md)
`privacy-proxy` is a runtime privacy protection plugin for OpenClaw.
Its purpose is not just to make logs look cleaner. It moves sensitive-data handling into the actual agent execution path:
1. Redact sensitive data before it reaches the model
2. Restore real values only for trusted tools and message actions
3. Restore or sanitize user-visible output based on policy
4. Sanitize content before it is written to `session.jsonl`
5. Sanitize content again before it is written to `MEMORY.md` or `memory/*.md`
If your goal is:
- the model should not see API keys, tokens, emails, phone numbers, or business IDs
- tools should still receive real values when they actually need them
- session and memory files should not persist raw secrets
then this plugin is built for that workflow.
## Verified Environment
The current documentation and validation results in this repository are based on:
- OpenClaw `2026.4.5`
- model `gpt-5.4`
- message channel `Discord`
## Use Cases
This plugin is useful when:
- user messages contain sensitive values directly
- environment variables are expanded into real values at runtime
- tool outputs are fed back into model context
- the agent needs real IDs, URLs, or tokens to execute tools
- you want end users to see real values, while keeping session and memory storage redacted
## What It Does
### 1. Redacts data before model execution
The plugin sanitizes model context before it is sent to the model.
Supported categories currently include:
- `secret`, such as API keys, bearer tokens, JWTs, bot tokens, and webhook secrets
- email addresses
- phone numbers
- payment card numbers
- national ID numbers
- structured business IDs such as `guildId`, `channelId`, `messageId`, and `userId`
- custom literals
- custom regex patterns
- explicit markers such as `PII[store_id]=123456789012345`
### 2. Restores real values only for allowed tools
This plugin does not restore real values for every tool by default.
The recommended model is:
- default to `passthrough`
- only restore for tools or message actions that truly require real values
That keeps unknown tools, external tools, and networked tools from receiving sensitive data by default.
### 3. Controls final user-visible output
The plugin supports four output modes:
- `restore`
- `scrub`
- `placeholder`
- `passthrough`
If you want "model sees redacted values, user sees real values", use:
```json
"messagePlaceholderPolicy": "restore"
```
### 4. Controls session persistence
The plugin sanitizes messages again before they are written to session history.
Common options:
- `placeholder`
- `scrub`
- `passthrough`
Recommended:
```json
"sessionPersistencePolicy": "placeholder"
```
### 5. Controls memory persistence
The plugin also protects writes performed through tools such as:
- `write`
- `edit`
- `apply_patch`
If the target file is:
- `MEMORY.md`
- `memory/*.md`
the content is sanitized again before persistence.
Recommended:
```json
"memoryPersistencePolicy": "scrub"
```
### 6. Supports explicit PII markers
Besides automatic detection, the plugin supports explicit marking:
```text
PII[store_id]=123456789012345
PII[api_key]=sk-test-1234567890abcdef
PII[url]="https://example.com/detail/76219040483288220"
```
This is useful when:
- your business-specific fields are not covered well by default heuristics
- you want to explicitly force a value into the reversible placeholder mapping
## How It Works
```text
user input / expanded config / tool output
-> sanitize before model execution
-> model only sees placeholders or scrubbed text
-> restore real values for allowed tools and message actions
-> restore or sanitize user-visible output based on policy
-> sanitize before session persistence
-> sanitize before memory persistence
```
Internally, this is not just a one-shot regex replacement. The plugin keeps reversible placeholder mappings for:
- real value -> placeholder
- placeholder -> real value
Those mappings are controlled by:
- `placeholderTtlMs`
- `maxEntries`
## Installation
### 1. Place the plugin in a local directory
Put this plugin in a path OpenClaw can access, for example:
```text
extensions/privacy-proxy
```
### 2. Register it in `openclaw.json`
The most common setup is a local path install:
```json
{
"plugins": {
"installs": {
"privacy-proxy": {
"source": "path",
"sourcePath": "/path/to/extensions/privacy-proxy",
"installPath": "/path/to/extensions/privacy-proxy"
}
},
"entries": {
"privacy-proxy": {
"enabled": true,
"config": {}
}
}
}
}
```
### 3. Restart OpenClaw
After changing plugin code or configuration, restart OpenClaw so the new settings take effect.
## Recommended Configuration
The following config is a good starting point for most setups:
```json
{
"plugins": {
"entries": {
"privacy-proxy": {
"enabled": true,
"config": {
"debugToolRestore": false,
"detectors": {
"secret": true,
"email": true,
"phone": true,
"identifier": true,
"paymentCard": true,
"nationalId": true
},
"customPatterns": [],
"customLiterals": [],
"placeholderTtlMs": 86400000,
"maxEntries": 2048,
"trace": {
"enabled": false,
"summaryOnly": true
},
"messagePlaceholderPolicy": "restore",
"restoreDiscordOutboundMessages": true,
"sessionPersistencePolicy": "placeholder",
"memoryPersistencePolicy": "scrub",
"defaultToolRestoreMode": "passthrough",
"restoreAllowedTools": [
"write",
"edit",
"apply_patch",
"exec"
],
"restorePassthroughTools": [],
"restoreAllowedMessageActions": [
"channel-info",
"channel-list",
"channel-create",
"channel-edit",
"channel-delete",
"channel-move",
"category-create",
"category-edit",
"category-delete"
],
"identifierKeys": [],
"unresolvedPlaceholderPolicy": "block"
}
}
}
}
}
```
This configuration gives you:
- model-side redaction
- allowlist-based restore for trusted tools
- restored user-visible replies
- placeholder-based session persistence
- scrubbed memory persistence
## Key Configuration Options
### `messagePlaceholderPolicy`
Controls the final user-visible message behavior.
Available values:
- `restore`
- `scrub`
- `placeholder`
- `passthrough`
Recommended:
```json
"messagePlaceholderPolicy": "restore"
```
### `sessionPersistencePolicy`
Controls how content is handled before writing to `session.jsonl`.
Available values:
- `placeholder`
- `scrub`
- `passthrough`
Recommended:
```json
"sessionPersistencePolicy": "placeholder"
```
### `memoryPersistencePolicy`
Controls how content is handled before writing to `MEMORY.md` and `memory/*.md`.
Available values:
- `scrub`
- `placeholder`
- `passthrough`
Recommended:
```json
"memoryPersistencePolicy": "scrub"
```
### `defaultToolRestoreMode`
Controls the default restore behavior for tool calls.
Available values:
- `restore`
- `passthrough`
Recommended:
```json
"defaultToolRestoreMode": "passthrough"
```
Then only opt in the tools or message actions that truly need real values.
### `restoreAllowedTools`
Allowlist of tools that may receive restored real values.
Typical examples:
- `write`
- `edit`
- `apply_patch`
- `exec`
- `browser`
### `restoreAllowedMessageActions`
Allowlist of message actions that may receive restored real values.
For Discord or channel-management use cases, common entries include:
- `channel-info`
- `channel-list`
- `channel-create`
- `channel-edit`
- `channel-delete`
- `channel-move`
- `category-create`
- `category-edit`
- `category-delete`
### `identifierKeys`
Adds custom structured ID keys.
Many common ID fields are already covered by default, such as:
- `guild_id`
- `channel_id`
- `thread_id`
- `user_id`
- `message_id`
If your business uses additional keys, extend them here:
```json
"identifierKeys": [
"store_id",
"merchant_id",
"order_id"
]
```
### `restoreDiscordOutboundMessages`
This field is easy to misunderstand.
What it actually does:
- when the plugin receives a `message_sending` event with `metadata.channel === "discord"`
- it decides whether to apply final restore for that outbound Discord message
What it does not do:
- it does not patch OpenClaw's Discord extension for you
- it does not automatically wire Discord monitor direct-send flows into `message_sending`
In other words:
> This is a processing switch, not a wiring switch.
## Discord Direct Replies
This is the most important boundary to understand.
### What works with the plugin alone
If you only install this plugin, you still get:
- model-side redaction
- tool-side restore
- session and memory sanitization
### What does not automatically work with the plugin alone
This does not automatically guarantee:
- Discord monitor direct replies will show restored plaintext to end users
### Why
The plugin performs final user-visible restore in the `message_sending` hook.
If your OpenClaw Discord extension does not trigger `message_sending` before its final outbound send, then:
- enabling `restoreDiscordOutboundMessages` is not enough
- direct Discord monitor replies will not automatically gain restored plaintext output
### When source changes are required
If you want this behavior:
```text
Discord monitor sends a direct reply
-> message passes through privacy-proxy's message_sending restore
-> Discord user sees restored plaintext
```
then your OpenClaw Discord extension must explicitly wire its final send path into the existing `message_sending` and `mess
... (truncated)
integration
Comments
Sign in to leave a comment