OGuardAI
Getting Started

Quick Start

Get OGuardAI running and make your first API call in under a minute

Start the Server

docker run -p 3000:3000 \
  -e GUARDAI_SESSION_SECRET=$(openssl rand -base64 32) \
  ghcr.io/oronts/oronts-guardai/oguardai-server:latest

One binary. Built-in regex detectors. Sealed sessions. No Python, no Redis.

How It Works

Check Health

curl http://localhost:3000/v1/health
# {"status":"healthy","version":"0.1.0","uptime_seconds":1.2, ...}
# The full response also carries a "components" block (detector, session, policies) with a per-component status and message.

Transform Text

Send sensitive text to OGuardAI. It detects PII, replaces it with semantic tokens, and returns the safe version along with an encrypted session state blob.

curl -X POST http://localhost:3000/v1/transform \
  -H "Content-Type: application/json" \
  -d '{"input": "Contact julia@example.com about invoice #12345"}'

Response:

{
  "safe_text": "Contact {{email:e_001:7b1068662ab5}} about invoice #12345",
  "session_id": "01916a3e-7b2c-7000-8000-000000000001",
  "session_state": "eyJhbGci...",
  "entities": [
    {
      "token": "{{email:e_001:7b1068662ab5}}",
      "type": "email",
      "span": { "start": 8, "end": 23 }
    }
  ]
}

The third token segment is a random per-token capability suffix. Rehydrate resolves a token only on an exact {{type:id:cap}} match, so a guessed or truncated token is left unresolved (fail closed). Pass the LLM output back verbatim.

Rehydrate (Restore)

After the LLM responds using the tokenized text, restore the original values:

curl -X POST http://localhost:3000/v1/rehydrate \
  -H "Content-Type: application/json" \
  -d '{
    "output": "I have emailed {{email:e_001:7b1068662ab5}} about the invoice.",
    "session_state": "eyJhbGci..."
  }'

Response:

{
  "restored_text": "I have emailed julia@example.com about the invoice."
}

What Happened

  1. OGuardAI detected julia@example.com as an email entity
  2. Replaced it with {{email:e_001:7b1068662ab5}}, a semantic token the LLM can reason about
  3. Stored the mapping in an AES-256-GCM encrypted session blob
  4. On rehydrate, decrypted the blob and restored the original value

The LLM never saw the real email address.

Detect Only

You can also run detection without transformation to see what entities OGuardAI finds:

curl -X POST http://localhost:3000/v1/detect \
  -H "Content-Type: application/json" \
  -d '{"input": "SSN: 123-45-6789, email: julia@example.com", "include_values": false}'

Round-Trip Test

Run a full transform-then-rehydrate cycle to verify end-to-end behavior:

# Transform
RESPONSE=$(curl -s -X POST http://localhost:3000/v1/transform \
  -H "Content-Type: application/json" \
  -d '{"input": "Contact Julia at julia@example.com or call 555-0123."}')
echo "$RESPONSE" | jq .

# Rehydrate
SESSION_STATE=$(echo "$RESPONSE" | jq -r '.session_state')
curl -s -X POST http://localhost:3000/v1/rehydrate \
  -H "Content-Type: application/json" \
  -d "{\"output\": $(echo "$RESPONSE" | jq '.safe_text'), \"session_state\": \"$SESSION_STATE\"}" \
  | jq .

Using the CLI

If you have the OGuardAI CLI installed, you can transform and detect from the command line:

oguardai transform --input "Contact julia@example.com"
oguardai detect --input "SSN: 123-45-6789"

Using the OpenAI Proxy

For the fastest integration with existing OpenAI code, start the proxy and change one URL:

# Start the proxy
oguardai-proxy --target https://api.openai.com --policy default --port 8081
from openai import OpenAI

client = OpenAI(
    api_key="sk-...",
    base_url="http://localhost:8081/v1"  # Only change needed
)
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Contact julia@example.com or call +49 30 12345678"}]
)
# OpenAI sees: "Contact `{{email:e_001:4c19f2d8b7a3}}` or call `{{phone:ph_001:d82a05c1f4e6}}`"
# Response is automatically restored before reaching your code

Docker Compose (Full Stack)

For a full local setup with NER detection:

GUARDAI_SESSION_SECRET=$(openssl rand -base64 32) \
GUARDAI_API_KEY_1=$(openssl rand -hex 32) \
  docker compose -f deploy/docker/docker-compose.yml up --build

This starts the Rust API server (port 3000) and Python NER detector (port 9090).

Common Endpoints

EndpointPurpose
POST /v1/transformTransform text, return safe output + session state
POST /v1/rehydrateRestore tokens using session state
POST /v1/detectDetect entities only (no transformation)
POST /v1/evaluate-policyEvaluate policy against entities
GET /v1/healthHealth check
GET /v1/capabilitiesList entity types, languages, detectors
POST /v1/transform/streamStream transform with SSE
POST /v1/rehydrate/streamStream rehydrate with SSE

These are the endpoints most integrations start with. The runtime exposes more (batch, RAG, file and image transforms, sessions, revocation, admin); see the API Reference for the full route set, scopes, and error codes.

Next Steps