OGuardAI
Guides

Migration Guide

Migrate existing AI applications to OGuardAI with minimal code changes

You do not need to rewrite your application. OGuardAI is designed to slot into existing AI workflows with minimal changes. Most migrations require changing one line of code or adding a thin middleware layer.


Migration Paths

Current SetupMigration PathEffort
OpenAI / Anthropic APISet base_url to the OGuardAI proxy and add the proxy key header2 lines
LangChain agentAdd OGuardAI LangChain adapter3 lines
Vercel AI SDKAdd OGuardAI Vercel AI adapter3 lines
Python backend (FastAPI)Add OGuardAI middleware5 lines
Node.js backend (Express)Add OGuardAI middleware5 lines
Custom HTTP pipelineCall transform before LLM, rehydrate after10 lines
RAG pipelineUse 4-step API (transform, index, search, rehydrate)Replace ingestion step

Migration 1: OpenAI Proxy (Lowest Effort)

If your application calls the OpenAI or Anthropic API directly, point its base_url at OGuardAI's proxy and add the X-GuardAI-API-Key header to authenticate to the proxy. Those two lines are the only changes.

Before:

from openai import OpenAI

client = OpenAI(api_key="sk-...")
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Help customer Erika Mustermann (erika.mustermann@example.com)"}]
)
# PII sent directly to OpenAI

After:

from openai import OpenAI
import os

client = OpenAI(
    api_key="sk-...",
    base_url="http://localhost:8081/v1",  # <-- point at the proxy
    default_headers={"X-GuardAI-API-Key": os.environ["GUARDAI_PROXY_API_KEY"]},  # <-- authenticate to the proxy
)
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Help customer Erika Mustermann (erika.mustermann@example.com)"}]
)
# OpenAI sees: "Help customer `{{person:p_001:ad4f97591c16}}` (`{{email:e_001:1bcaef1a4aff}}`)"
# Response is automatically restored before reaching your code

Setup:

Availability: The proxy image below is private today and provided under a written agreement with Oronts. Request access at /request.

# Generate one proxy key; the proxy and the client (above) must present the same value.
export GUARDAI_PROXY_API_KEY=$(openssl rand -hex 32)

# Start the proxy from the published image; --network host serves it on the host's localhost:8081.
docker run --rm --network host \
  -e GUARDAI_SESSION_SECRET=$(openssl rand -base64 32) \
  -e GUARDAI_PROXY_API_KEY \
  ghcr.io/oronts/oguardai/proxy:0.1.0 \
  --target https://api.openai.com --policy default --port 8081 \
  --single-tenant --rate-limit-enabled

Run the client in the same shell where you exported GUARDAI_PROXY_API_KEY, so its X-GuardAI-API-Key header matches the proxy. A non-dev proxy requires a proxy key (GUARDAI_PROXY_API_KEY) and a bounded rate limiter (--rate-limit-enabled), and single-tenant auth needs the --single-tenant acknowledgement. For a throwaway local proxy you can instead set GUARDAI_PROXY_DEV=1, which waives the key and limiter. See the OpenAI Proxy guide for the full setup. Streaming, tool calls, and all message roles are handled transparently.


Migration 2: Python Middleware (FastAPI)

Add OGuardAI as FastAPI middleware. Incoming text is tokenized; outgoing responses are restored. Route handler code does not change.

# Add transform/rehydrate calls around your LLM interaction:
from guardai_sdk import OGuardAIClient

guardai = OGuardAIClient(base_url="http://localhost:3000")

@app.post("/chat")
async def chat(message: str):
    # Transform: mask PII before sending to LLM
    result = guardai.transform(message)
    llm_reply = call_llm(result.safe_text)
    # Rehydrate: restore PII in the response
    restored = guardai.rehydrate(llm_reply, session_state=result.session_state)
    return {"reply": restored.restored_text}

Migration 3: Node.js Middleware (Express)

Same pattern for Express. Add the middleware; routes stay unchanged.

// Add transform/rehydrate calls around your LLM interaction:
import { OGuardAIClient } from "@oguardai/sdk";

const guardai = new OGuardAIClient({ baseUrl: "http://localhost:3000" });

app.post("/chat", async (req, res) => {
  // Transform: mask PII before sending to LLM
  const result = await guardai.transform({ input: req.body.message });
  const reply = await callLlm(result.safe_text);
  // Rehydrate: restore PII in the response
  const restored = await guardai.rehydrate({ output: reply, session_state: result.session_state! });
  res.json({ reply: restored.restored_text });
});

What Changes vs. What Stays the Same

AspectChangesStays the Same
LLM callsRouted through OGuardAI (proxy or middleware)Same API, same models, same prompts
Application code1-5 lines addedBusiness logic, routes, database queries
LLM providerReceives tokenized text instead of raw PIISame provider, same billing, same models
Output qualityThe model receives semantic tokens plus any policy-permitted metadata (gender, formality, language) instead of raw PII; validate output quality against your own inputsTone, style, language, format
InfrastructureOne new service (OGuardAI binary or container)Everything else
AuthenticationAdd OGuardAI API key to configYour existing auth unchanged

Rollback and Gradual Rollout

Shadow Mode (Staging Only)

Enable shadow mode in a non-production environment to measure detection coverage before you widen the rollout:

transform:
  shadow_mode: true

Shadow mode does not weaken protection. The full pipeline still runs and safe_text is still tokenized; the response simply carries an extra shadow block for comparison: a keyed HMAC fingerprint of the input (stable only within one running process, so two responses are comparable only there), the original and protected character lengths, and the number of entities masked. The original text is never returned. It is a dev-only diagnostic, and production validation rejects it as a fatal startup error, so run it in staging while you review detection counts.

  1. Pick one non-critical AI workflow and route it through OGuardAI in shadow mode in a staging environment.
  2. Run shadow mode for 1-2 weeks. Review the per-request masked-entity counts and length deltas against your own corpus.
  3. Set transform.shadow_mode: false before promoting to production; the server refuses to start otherwise. Monitor for regressions.
  4. Expand to additional workflows with per-workflow policies.
  5. Add the NER sidecar if you need person/company/location detection beyond regex.

Emergency Rollback

  • Proxy mode: Change base_url back to the LLM provider URL. One line.
  • Middleware mode: Remove the middleware line. Redeploy.
  • No client-side data migration. By default session state travels in client-held sealed blobs, not a server store, so removing OGuardAI from the request path restores your prior data flow; an optional Redis session backend for multi-replica deployments instead holds that state server-side under a TTL. OGuardAI's own operational stores are separate and persist independently of the rollback: the durable audit log (audit.backend: file), the revocation and request-replay stores (Redis in a multi-replica deployment), and any RAG corpus. Back up and retire those on your own schedule.