local-pii
Adapters

Vercel AI SDK

Wrap any AI SDK language model so prompts are anonymized and responses — including tool calls and streams — are rehydrated.

local-pii/ai-sdk is a Vercel AI SDK middleware. It anonymizes every prompt (text, history, tool-call arguments, tool results) on the way to the provider and rehydrates everything on the way back — generated text, tool-call arguments (so the agent loop runs your tools with real values), and streamed deltas across chunk boundaries.

bun add ai local-pii

Usage

import { openai } from "@ai-sdk/openai"
import { streamText, generateText } from "ai"
import { withPii } from "local-pii/ai-sdk"

const model = withPii(openai("gpt-5.2"))

const { text } = await generateText({
  model,
  prompt: "Draft a reply to ana@acme.com",
})
// the provider saw [EMAIL_1]; `text` has the address back

withPii(model, opts?) is sugar over wrapLanguageModel({ model, middleware: piiMiddleware(opts) }).

Tools

No tool wrapper is needed — the middleware rehydrates tool-call arguments before the SDK executes your tool, and re-anonymizes the tool result on the next step.

import { streamText, tool, stepCountIs } from "ai"
import { z } from "zod"
import { withPii } from "local-pii/ai-sdk"

const result = streamText({
  model: withPii(openai("gpt-5.2")),
  stopWhen: stepCountIs(5),
  tools: {
    lookup: tool({
      description: "Look up a contact",
      inputSchema: z.object({ email: z.string() }),
      execute: async ({ email }) => findContact(email), // real email here
    }),
  },
  prompt: "look up ana@acme.com and summarize",
})

Sessions

Create one session per conversation (per request on a server):

const session = anonymizer.createSession()
const model = withPii(baseModel, { session })

Use the opaque token() strategy when tools are enabled. See Tool Calls for the full round-trip and the third-party caveat.

On this page