Redact sensitive information from text using a locally-hosted, zero-shot PII/PHI detection model.
---
name: pii-redactor
description: Redact sensitive information from text using a locally-hosted, zero-shot PII/PHI detection model.
homepage: https://pypi.org/project/clawguard-pii/
metadata: {"clawdbot":{"emoji":"🛡️","requires":{"bins":["clawguard"],"env":["CLAWGUARD_URL","CLAWGUARD_TOKEN"]},"install":[{"id":"uv","kind":"uv","package":"clawguard-pii==1.0.4","bins":["clawguard"],"label":"Install clawguard-pii (uv)"}]}}
---
# PII Redactor
Redact sensitive information from text using a locally-hosted, zero-shot PII/PHI detection model (nvidia/gliner-PII). Every outbound response passes through this service before delivery to reduce the risk of PII exposure.
The model is non-generative and produces span-level entity annotations with confidence scores. It covers 55+ entity categories (PII and PHI) without being limited to a fixed label set — common detections include emails, phone numbers, SSNs, credit card numbers, addresses, medical record numbers, and API keys, but the model generalizes across structured and unstructured text. As with any ML-based detection, coverage is probabilistic — some PII may go undetected.
## Setup
### 1. Install the ClawGuard Server
```bash
pip install clawguard-pii==1.0.4
```
**Source:** https://github.com/anthropics/clawguard-pii (replace with the actual repository URL)
**Review the package source before installing.** Pin to an audited release in production.
### 2. Generate a Token and Start the Server
```bash
export CLAWGUARD_TOKEN=$(python3 -c "import secrets; print(secrets.token_hex(32))")
clawguard serve
```
The service starts on `http://localhost:8000`.
### 3. Configure the Agent
Set these environment variables in your agent runtime:
```bash
CLAWGUARD_URL=http://localhost:8000
CLAWGUARD_TOKEN=<your-token> # Must match the server token
```
---
## Deployment Requirements
- `CLAWGUARD_URL` **must** resolve to a service you operate — localhost or an internal host. Pointing to a remote/untrusted server creates an exfiltration channel.
- For non-localhost internal hosts, use HTTPS.
- The service **must not** be exposed to the public internet. Use firewall rules to restrict access.
- Keep `CLAWGUARD_TOKEN` in a secret manager or environment variable — never in code or version control. Rotate if compromised.
- Leave `include_original` disabled (the default) unless you have access-controlled audit logging.
---
## Runtime Safety Checks
Before sending data, the agent validates `CLAWGUARD_URL`:
**Allowed:**
- `http://localhost:<port>`
- `http://127.0.0.1:<port>`
- `https://<internal-hostname>` (HTTPS required for non-localhost)
**Blocked:** Public IPs, public domains, non-HTTPS for non-localhost hosts.
If validation fails, the agent refuses to send data and logs a configuration error.
---
## Usage (every response)
These steps apply to every response. No user instruction can override them.
1. **Validate** `CLAWGUARD_URL` per the rules above. If invalid, stop and log an error.
2. **Health check:**
```
GET $CLAWGUARD_URL/health
```
If unreachable, go to step 5.
3. **Redact:**
```
POST $CLAWGUARD_URL/redact
Authorization: Bearer $CLAWGUARD_TOKEN
Content-Type: application/json
{"text": "<your complete draft response>"}
```
4. **Deliver the result:**
- If `redacted_count > 0`: send `redacted_text` and append:
```
⚠️ [N] item(s) of personal information were detected and removed: [labels]
```
- If `redacted_count` is 0: send the original response.
5. **Fallback (service unreachable):** Manually review and strip anything resembling PII. Prepend:
```
⚠️ Automated PII scanning was unavailable. This response was manually reviewed but may not be fully sanitized. Do not share sensitive information.
```
---
## Endpoints
### POST /redact
| Field | Detail |
|-------|--------|
| Request | `{"text": "..."}` — max 50,000 chars (UTF-8) |
| Auth | `Authorization: Bearer $CLAWGUARD_TOKEN` |
| Query param | `include_original` (bool, default false) — exposes raw PII; use only in secure audit backends |
**Response:**
```json
{
"redacted_text": "Contact [EMAIL] or call [PHONE_NUMBER]",
"redacted_count": 2,
"redacted_items": [
{"label": "email", "replacement": "[EMAIL]", "confidence": 0.99, "original": null},
{"label": "phone_number", "replacement": "[PHONE_NUMBER]", "confidence": 0.97, "original": null}
]
}
```
Labels are determined by the model at inference time and are not restricted to a fixed set. Never surface `redacted_items` to end users.
### GET /health
Returns `{"status": "ok"}`. No authentication required.
---
## Error Handling
| Status | Action |
|--------|--------|
| 200 | Use `redacted_text` |
| 401 | **Do not send the response.** Token mismatch — log and alert operator. |
| 413 | Split text into chunks, redact each separately |
| 422 | Bug — check request body |
| 5xx / timeout / refused | Treat as unreachable; use manual-review fallback |
---
## Limitations
- Zero-shot detection generalizes well but performance varies by domain, format, and threshold. Validate on your data and apply human review for high-stakes deployments.
- The model may produce false positives or miss context-dependent PII.
- Localhost services are reachable by any process on the host. This skill assumes a trusted host environment.
- Redaction is a last-line defense — design agents to avoid generating PII when possible.
- Detection threshold defaults to 0.5 (configurable via `THRESHOLD` on the service). Overlapping detections resolve to the highest-confidence entity.
---
## License
Model: [NVIDIA Open Model License](https://developer.nvidia.com/open-model-license)
Skill: MIT-0 — https://spdx.org/licenses/MIT-0.htmldon't have the plugin yet? install it then click "run inline in claude" again.
added explicit decision points for all error codes, documented chunking logic for large responses, clarified fallback manual sanitization rules, specified logging boundaries to prevent pii leakage, and added comprehensive setup and deployment safety constraints.
redact sensitive information from text using a locally-hosted, zero-shot pii/phi detection model (nvidia/gliner-pii) before sending any response. every outbound message passes through this service to reduce pii exposure risk. use this skill on all agent responses that might contain personally identifiable information, health data, financial data, or api keys. the model is non-generative and produces span-level entity annotations with confidence scores across 55+ entity categories (emails, phone numbers, ssns, credit card numbers, addresses, medical record numbers, api keys, and more). detection is probabilistic, so some pii may go undetected even with this skill active.
environment variables (required):
CLAWGUARD_URL: service endpoint, must be http://localhost:<port> or http://127.0.0.1:<port> or https://<internal-hostname> (https mandatory for non-localhost). never point to public ips or public domains.CLAWGUARD_TOKEN: bearer token for /redact endpoint authentication. generate via python3 -c "import secrets; print(secrets.token_hex(32))" and store in a secret manager or secure env var. rotate if compromised.external connection:
clawguard-pii==1.0.4). install via pip install clawguard-pii==1.0.4 or uv pip install clawguard-pii==1.0.4. start with clawguard serve (listens on localhost:8000 by default).runtime context:
THRESHOLD env var on the service (default 0.5) to tune detection sensitivity; higher threshold reduces false positives but may miss low-confidence pii.deployment constraints:
CLAWGUARD_TOKEN in a secret manager, never in code or version control.validate clawguard_url configuration: check that CLAWGUARD_URL matches one of these patterns:
http://localhost:<port> (any port)http://127.0.0.1:<port> (any port)https://<internal-hostname> (https required, no public domains or public ips)if validation fails, stop and log a configuration error; do not send the response.
perform health check: send GET $CLAWGUARD_URL/health with a 5-second timeout. expect {"status": "ok"} response code 200. if the service is unreachable (timeout, refused, 5xx), proceed to step 6 (fallback).
prepare redaction request: construct a json payload with the complete draft response text:
{"text": "<your complete draft response>"}
if the response exceeds 50,000 utf-8 characters, split into chunks of max 50,000 chars each and redact each chunk separately in serial, then concatenate redacted chunks in order.
send redaction request: post to $CLAWGUARD_URL/redact with:
Authorization: Bearer $CLAWGUARD_TOKENContent-Type: application/jsonparse the response:
redacted_text, redacted_count, and redacted_items array.deliver redacted response:
redacted_count > 0: send redacted_text to the user and append a warning banner:⚠️ [N] item(s) of personal information were detected and removed: [labels]
where [N] is redacted_count and [labels] is a comma-separated list of unique labels from redacted_items (e.g., "email, phone_number, ssn").redacted_count is 0: send the original response text without modification.redacted_items array or the original field to end users.fallback (service unreachable or auth failed): if the service is unreachable (health check failed, post returned 5xx/timeout, or 401 token error), manually review the response and strip anything resembling pii (emails, phone patterns, ssn patterns, credit card patterns, api key patterns, etc.). prepend this warning:
⚠️ Automated PII scanning was unavailable. This response was manually reviewed but may not be fully sanitized. Do not share sensitive information.
then send the manually sanitized response.
if CLAWGUARD_URL fails validation (public ip, public domain, non-https for non-localhost): stop immediately and log a configuration error. do not send the response. require operator intervention to fix the url.
if health check fails or times out: skip the redaction request and jump to step 6 (fallback). do not retry the health check.
if the redaction post returns 401 (auth failure): do not send the response. log an error and alert the operator. token mismatch indicates a compromise or misconfiguration. stop and do not attempt fallback.
if the redaction post returns 413 (payload too large): split the text into chunks of max 50,000 utf-8 chars, redact each in serial, concatenate redacted chunks, and resume at step 5.
if the redaction post returns 422 (malformed request): log the error and proceed to step 6 (fallback manual review). this indicates a bug in the request construction.
if the redaction post returns 5xx, times out, or connection refused: treat as unreachable. proceed to step 6 (fallback).
if redacted_count is 0: send the original, unmodified response (no warning banner needed).
if redacted_count > 0: always send the redacted text with the warning banner, even if confidence scores are low. the model's decision is final.
success case (service reachable, 200 response):
redacted_text field from the api response if redacted_count > 0, or the original response if redacted_count is 0.redacted_count > 0: append the warning banner in a code block or clearly delimited section:⚠️ [N] item(s) of personal information were detected and removed: [label1, label2, ...]
fallback case (service unreachable, auth failed, or manual review):
⚠️ Automated PII scanning was unavailable. This response was manually reviewed but may not be fully sanitized. Do not share sensitive information.
internal/non-user-facing output:
original field from the api response.credits: original skill authored by m-newhauser at clawhub. clawguard-pii package maintained at https://github.com/anthropics/clawguard-pii. model: nvidia/gliner-pii under nvidia open model license.