Skip to main content

Legend

Python License PyPI Downloads Status

PII pseudonymization for the full agentic loop.


Agent pipelines expose PII at every step: in user prompts, tool call arguments, tool results, and final responses. Legend intercepts at all four points, replacing PII with realistic pseudonyms before it reaches external APIs or leaves your infrastructure, and restoring the original values exactly in the final response.


Design

The pseudonymization strategy is grounded in recent research showing that realistic substitutes preserve utility significantly better than suppression or redaction across multi-turn interactions. Legend extends the single-boundary pseudonymization approach of LOPSIDED (Serenari & Lee, 2025) to the full four-boundary agentic loop, addressing the leakage surface that existing tools leave uncovered.


Getting Started

Requirements

  • Python 3.13+
  • No external API keys. Legend runs entirely on your infrastructure.

Install

pip install legend
legend download-models

The download-models command fetches the spaCy model weights to ~/.legend/models/. Run this once before first use. If you skip it, Legend downloads the model automatically on first run.

For custom model locations (containerized or edge deployments), set LEGEND_MODEL_PATH before running:

LEGEND_MODEL_PATH=/mnt/storage/legend 
legend download-models

Use

import asyncio
from legend import DetectionPipeline, ReplacementEngine, PseudonymContext

pipeline = DetectionPipeline(entities=["PERSON", "EMAIL_ADDRESS", "US_SSN"])
engine = ReplacementEngine()

async def run():
    async with PseudonymContext(pipeline=pipeline, engine=engine) as ctx:

        # Boundary A: user prompt entering the agent
        prompt = await ctx.sanitize_prompt(
            "Process a refund for John Smith (john.smith@acme.com), SSN 123-45-6789."
        )
        # "Process a refund for Michael Torres (fake3847@example.com), SSN 987-65-4320."

        # Boundary B: tool call arguments leaving toward an external API
        args = await ctx.sanitize_tool_args({"email": "john.smith@acme.com", "amount": 150})
        # {"email": "fake3847@example.com", "amount": 150}

        # Boundary C: tool results entering the agent context
        result = await ctx.sanitize_tool_result(tool_response)

        # Boundary D: real values restored in the final response
        response = await ctx.revert(agent_response)

asyncio.run(run())

DetectionPipeline and ReplacementEngine are initialized once and reused across sessions. A fresh session-scoped entity map is created for each PseudonymContext block and destroyed on exit.


The Four Boundaries

Agent pipelines expose PII at four distinct points. Legend intercepts all of them.

A — User prompt in. PII in the user's message is replaced before it enters the agent's context window.

B — Tool call arguments out. PII that the agent constructs into tool call arguments is replaced before it reaches an external API, database, or service.

C — Tool result in. PII returned by a tool (fetched from a database, retrieved from an external system) is replaced before it enters the agent's context.

D — Response out. Pseudonyms are reverted to their original values in the final response before the user sees it.

Most tools protect only the prompt. Boundary B and Boundary C are where agent-specific leakage happens and where Legend is different.


Properties

Reversible. Real values are restored exactly at Boundary D. The agent's response reads naturally, with original names, addresses, and identifiers intact.

Realistic substitutes. A name becomes a plausible name. An IBAN becomes a valid-format IBAN with the correct country code and check digit. Agents reason correctly over pseudonymized data because the substitutes are semantically coherent.

Session-scoped. The entity map lives only for the duration of a PseudonymContext block. No state persists between sessions. No database required.

On-premise. Detection runs via YARA rules and a local spaCy model. Nothing leaves your infrastructure during processing.

Framework-agnostic. Works with LangGraph, LangChain, CrewAI, or any agent framework. PseudonymContext wraps your existing agent calls with no framework-specific integration required.


Custom Rules

Legend ships with detection rules covering the full Presidio entity list. For domain-specific PII formats (internal account IDs, regional document numbers, custom identifiers), generate additional YARA rules with yaramint and pass the rules directory to DetectionPipeline.


Roadmap

  • Framework adapters. One-line integration for LangChain, LangGraph, and CrewAI via wrap_langchain_tools() and equivalents. No tool-level boilerplate.
  • Transparent proxy. An OpenAI-compatible HTTP proxy that intercepts MCP tool calls at the protocol level. Works with any agent framework, zero code changes required.
  • OpenTelemetry integration. Optional legend[otel] extra that routes pseudonymized observability events into any OTel-compatible backend. Each session maps to a trace, each boundary to a child span.

References

Xiao, Yunze, Wenkai Li, Xiaoyuan Wu, Ningshan Ma, Yueqi Song, and Weihao Xuan. Say Something Else: Rethinking Contextual Privacy as Information Sufficiency. arXiv:2604.06409. Preprint, arXiv, April 7, 2026. https://doi.org/10.48550/arXiv.2604.06409.

Serenari, Jayden, and Stephen Lee. Semantically-Aware LLM Agent to Enhance Privacy in Conversational AI Services. arXiv:2510.27016. Preprint, arXiv, October 30, 2025. https://doi.org/10.48550/arXiv.2510.27016.

Metadata

Release files for legend-pii 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for legend-pii 0.1.0
File Size Uploaded
legend_pii-0.1.0.tar.gz 114.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for legend-pii 0.1.0
File Interpreter ABI Platform
legend_pii-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 155.9 kB

Release files / legend_pii-0.1.0.tar.gz

Download URL legend_pii-0.1.0.tar.gz
Size 114.9 kB
Tags Source
SHA-256 checksum
How to use checksums
74b2fae9c37b931666481fa7aaa180161fef5143ffe378cb9450d51f44053021
BLAKE2b-256 checksum
How to use checksums
1b509f9b094186855c027524676ed445d84fe17692b83359fbabb8b759b00deb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 29, 2026.

Transparency log

Release files / legend_pii-0.1.0-py3-none-any.whl

Download URL legend_pii-0.1.0-py3-none-any.whl
Size 41.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06ae096dd138b96c18b9fa61f9ff5f8831e082a3e1aba2ac4ecb0f9996992275
BLAKE2b-256 checksum
How to use checksums
90f48578779972a1cad5c95dee8fd53143448986dd6aafd101db4ce260fd9841
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page