OGuardAI
Integrations

Vercel AI SDK

Protect Vercel AI SDK generations with OGuardAI so PII is tokenized before the model and restored in the output

The OGuardAI TypeScript SDK ships an optional Vercel AI SDK integration that wraps a single text generation so PII in the prompt is tokenized before the model runs and restored in the model output afterward. The generate call and the model only ever see the tokenized safe_text; the sealed session never enters the AI SDK. The integration is a thin seam over the SDK guardedCall primitive.

Install

The integration has no dependency on the ai package: you pass your own generate function, so the adapter works against any ai version and any provider. Install the SDK and the AI SDK, plus the provider package that supplies your model (for example @ai-sdk/openai).

npm install @oguardai/sdk ai

One boundary-safe entry point

guardedGenerateText is the single entry point, and it is boundary-safe by design. The transform and the rehydrate run outside the AI SDK: your generate function is the only code that touches the model, and it only ever receives the tokenized prompt. No experimental_telemetry span inside the generate call, and no provider request, observes the raw prompt or the restored output.

Unlike the LangChain integration, there is no composable in-framework variant here, so there is no tracer-exposed path to caveat. The single seam keeps the raw input and the restored output on the host side of the boundary in every case.

Signature

function guardedGenerateText(
  generate: (safePrompt: string) => Promise<GenerateTextLike | string> | GenerateTextLike | string,
  client: OGuardAIClient,
  prompt: string,
  options?: GuardedGenerateOptions,
): Promise<string>;

type GenerateTextLike = { text: string };

interface GuardedGenerateOptions {
  policy?: string;
  language?: string;
  outputChannel?: OutputChannel;
  restoreMode?: RestoreMode;
}

generate receives the tokenized prompt and returns either the AI SDK result (any object with a string text, which is what generateText returns) or a plain string. guardedGenerateText returns the restored text as a plain string, not a result object.

OptionDefaultDescription
policyserver defaultOGuardAI policy name applied to the transform.
languageserver defaultLanguage hint for detection (for example de).
outputChanneluser_outputOutput channel whose restore rules apply on the way back.
restoreModefullRestore mode for the rehydrate step (full, partial, masked, formatted, abstract, none).

Usage

import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { OGuardAIClient } from "@oguardai/sdk";
import { guardedGenerateText } from "@oguardai/sdk/integrations/vercel";

const client = new OGuardAIClient({ baseUrl: "http://localhost:3000" });
const model = openai("gpt-4o-mini");

const reply = await guardedGenerateText(
  (safePrompt) => generateText({ model, prompt: safePrompt }),
  client,
  "Antworte Herrn Julian Schneider unter julian.schneider@firma.example",
  { policy: "german-support", language: "de", outputChannel: "customer_email" },
);

The generate closure runs on Antworte Herrn {{person:p_001:...}} unter {{email:e_001:...}} only. The returned reply has the real values restored per the customer_email channel.

What the model and tracer see

The prompt reaches the model as tokenized safe_text, never a raw value:

Antworte Herrn {{person:p_001:...}} unter {{email:e_001:...}}

Because the transform and rehydrate happen outside the AI SDK, an experimental_telemetry span opened inside your generateText call records only the tokenized prompt and the tokenized model output. The restoration happens after guardedGenerateText receives the model result, on the host side of the boundary, so no tracer, log, or provider request ever observes a raw or a restored name, email, or IBAN.

Scope

The adapter protects one prompt string. For a multi-message chat, use guardedChat and rehydrateResponse on the client directly, which share one sealed session across the conversation. Tokens embedded in tool-call arguments or intermediate agent steps are out of scope for this adapter and are not restored.

Fail-closed behavior

  • If the transform returns no sealed session, guardedGenerateText throws before the model is called, so a prompt that cannot later be restored or proven protected never reaches the provider.
  • If generate resolves to neither a string nor an object with a string text, the adapter throws a TypeError rather than returning an unverified value.

How it works

  1. The integration calls /v1/transform on the prompt, replacing PII with semantic tokens.
  2. Your generate function runs on the tokenized safe_text and returns its output.
  3. The integration calls /v1/rehydrate on that output using the sealed session, restoring the real values per the output channel.

If the transform fails or yields no session, the generate function is never invoked (fail closed).