Skip to main content

LangChain agent middleware that routes model calls through the NoPII PII-tokenization proxy

Project description

langchain-nopii-middleware

LangChain agent middleware that routes model calls through the NoPII tokenization proxy. Adds PII detection and tokenization to any LangChain agent in a single line, without changing how the model is constructed and without an SDK.

What it does

NoPII detects PII in outbound prompts, replaces it with deterministic tokens before the request reaches the LLM, and restores the original values in the response. The middleware sits inside the agent's model-call path and rebinds the model's API base URL to NoPII's proxy, so the underlying OpenAI/Anthropic SDK still handles the HTTP call. Your existing API key is forwarded to NoPII for tenant identification.

  • Drop-in: one middleware, no SDK
  • Deterministic tokenization: same plaintext → same token, so the model can reason consistently across multi-turn conversations
  • Fail-safe: requests are blocked if tokenization fails; PII never leaks
  • Full audit trail of every entity detected and tokenized

Installation

pip install langchain-nopii-middleware

Install with provider extras for the model you use:

pip install "langchain-nopii-middleware[openai]"
pip install "langchain-nopii-middleware[anthropic]"

Quick start

from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

from langchain_nopii_middleware import NoPIIMiddleware

agent = create_agent(
    model=ChatOpenAI(model="gpt-4.1"),
    tools=[...],
    middleware=[NoPIIMiddleware()],
)

result = agent.invoke({
    "messages": [
        {"role": "user", "content": "Email john.doe@example.com a meeting summary."}
    ]
})

The proxy receives the prompt with PII tokenized (e.g. <EMAIL_a3f2> in place of the address), forwards the tokenized prompt to OpenAI, and restores the original email in the response before it reaches the agent.

Configuration

NoPIIMiddleware(
    base_url="https://api.nopii.co",  # default; override for self-hosted or test environments
    session_id="user-42-thread-7",    # optional; pin a session for multi-turn token continuity
)

Session continuity

By default each model call gets a fresh tokenization session from the proxy. For multi-turn agents where the same PII should map to the same token across calls, pass an explicit session_id:

agent = create_agent(
    model=ChatAnthropic(model="claude-3-5-sonnet-latest"),
    tools=[...],
    middleware=[NoPIIMiddleware(session_id=conversation_id)],
)

Tokenization is deterministic at the proxy level regardless of session, but session_id is what lets the proxy detokenize tokens it issued on earlier turns when they appear in the model's response.

Supported models

Model class Provider extra
langchain_openai.ChatOpenAI [openai]
langchain_openai.AzureChatOpenAI [openai]
langchain_anthropic.ChatAnthropic [anthropic]

Other LangChain chat models can be added on request. See docs.nopii.co/integrations for the full list of LLM providers the underlying NoPII proxy supports.

How it works

  1. The agent calls model.invoke(...) (or ainvoke) as normal.
  2. NoPIIMiddleware.wrap_model_call intercepts the call and produces a copy of the model whose API base URL points at the NoPII proxy.
  3. The model's own SDK (openai or anthropic) sends the HTTP request — but to NoPII instead of the LLM provider.
  4. NoPII detects PII, tokenizes it, forwards the tokenized request to the LLM, then restores PII in the response before returning it.
  5. The agent receives the response with original PII intact.

The middleware does not introduce a second HTTP hop and does not buffer responses; streaming works.

Authentication

NoPII identifies tenants by hashing the LLM API key on the incoming request. Provide your real OpenAI/Anthropic key to the LangChain model exactly as you would without NoPII, and NoPII will resolve it to your tenant configuration. No separate NoPII API key is required for the proxy path.

For account setup and key registration, see docs.nopii.co/quickstart.

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_nopii_middleware-0.1.0.tar.gz (7.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_nopii_middleware-0.1.0-py3-none-any.whl (6.3 kB view details)

Uploaded Python 3

File details

Details for the file langchain_nopii_middleware-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_nopii_middleware-0.1.0.tar.gz
  • Upload date:
  • Size: 7.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langchain_nopii_middleware-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3f73c4954948b0436758d1781042ec0679f333edeecceffef79f257244f76182
MD5 a245ae87e07059879f73204397e5cc78
BLAKE2b-256 e460e2ead34cbe1387adada50efafb2d7c90d791bb12c68cd15afc4704f5e302

See more details on using hashes here.

File details

Details for the file langchain_nopii_middleware-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: langchain_nopii_middleware-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langchain_nopii_middleware-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b74e3e18f3957f4f419f0ec665e61625f19e7fe4c7301972593d81296a5af367
MD5 181117404c9d06669915074990ddc9c5
BLAKE2b-256 4252adc4079a5f142b740e1bc2f8d3c307fd4ca44e581b7a4416a99a577280ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page