Skip to content

P1-2: Lakera, Presidio, OpenAI Moderation guardrails (3-pack) #52

Description

@moonming

Summary

Three guardrail integrations that come up in ~80% of security-conscious procurement conversations, each closing a category where competitors currently lead us:

  1. Lakera Guard — prompt-injection / jailbreak detection (POST https://api.lakera.ai/v2/guard, Bearer token).
  2. Microsoft Presidio — PII detection + redaction, self-hosted (POST {analyzer_url}/analyze + POST {anonymizer_url}/anonymize).
  3. OpenAI Moderation — category content moderation, free (POST https://api.openai.com/v1/moderations).

Revised 2026-07-06 — the original body (written 2026-05-29) predated a large batch of guardrail platform work (#694 pii kind, #719 Bedrock ANONYMIZE, enforcement_mode=monitor, output-side redaction incl. streaming). Every platform prerequisite it listed as blocked is now shipped; the plan below is updated accordingly. Repo pointers refreshed: DP = api7/aisix (renamed from ai-gateway), CP+UI = api7/AISIX-Cloud, user docs = api7/docs under docs/ai-gateway/.

Current shipped state (origin/main, 2026-07-06)

Guardrail kinds are keyword, pii (built-in detectors + custom regex, mask/block, input+output incl. streaming — #694), bedrock (incl. sensitive-info filters with ANONYMIZE mask-and-continue — #719), azure_content_safety (Prompt Shield), azure_content_safety_text_moderation, and aliyun_text_moderation. None of Lakera, Presidio, or OpenAI Moderation exist yet.

Platform capabilities the original plan can now assume instead of building:

  • Output-side redaction is shipped. The old Rewrite{payload} verdict no longer exists; redaction goes through the Guardrail trait's redact_input_text / redact_output_text (+ SegmentsOutcome for segment moderation), with streaming handled by StreamOutputPolicy::BufferFull hold-back and capture rebuild. Presidio output-redact is therefore in scope for this pass — the follow-up split is obsolete.
  • Monitor mode is a platform feature. enforcement_mode: monitor|block wraps any kind in a MonitorGuardrail decorator (observes, never blocks/redacts, no stream hold-back). The bespoke flag_only action originally planned for OpenAI Moderation is unnecessary — drop it.
  • Credential handling: org-scoped encrypted credentials (Bedrock/ACS/Aliyun pattern) — ciphertext at rest in cp-api, plaintext only in the in-memory DP snapshot, blank-on-edit in the UI.
  • fail_open / output_fail_open, mandatory (fail-closed), per-request applied_guardrails telemetry, and the DP heartbeat supported_kinds gate all exist.

Note on the generic webhook: #61 proposes a universal webhook guardrail kind that can reach any HTTP guardrail vendor with zero per-vendor DP code (LiteLLM baseline: generic_guardrail_api). Lakera and OpenAI Moderation could in principle be driven through it. They are still worth a small bespoke module here because (a) they're the highest-volume procurement asks and deserve first-class UI/validation, and (b) Presidio's two-call analyze→anonymize flow needs native handling the generic webhook does not model. Treat this issue as the "first-class three"; everything else goes through the webhook (#61, deliberately deferred).

Cross-repo scope

Each integration is a Guardrail trait impl in its own module of aisix-guardrails, plus a GuardrailKind variant + regenerated resource schema + CP descriptor + schema-driven UI form + e2e.

  • DP (api7/aisix): lakera (input-focused), presidio (input + output, block/redact), openai_moderation (input-focused) modules in crates/aisix-guardrails.
  • CP (api7/AISIX-Cloud): guardrail config descriptors (internal/cpapi/resources/guardrail_schema*.go) for the three kinds — the dashboard renders forms from the served JSON Schema (SchemaForm), so no hand-coded React form per kind. Kind validation + etcd projection + encrypted secrets.
  • Docs (api7/docs): one page per kind under docs/ai-gateway/traffic-controls/guardrails/, paired PR.

2. Research (verify each schema against the primary source before coding; LiteLLM latest is the behavior baseline — lakera_ai_v2.py, presidio.py, OpenAI moderation hook)

Lakera Guard — prompt-injection / jailbreak / PII / content detection.

  • API: POST https://api.lakera.ai/v2/guard, Authorization: Bearer <key>. Returns per-category detections and a top-level flagged boolean. Docs: https://docs.lakera.ai

Microsoft Presidio — open-source, self-hosted PII detection + anonymization (no vendor key; the customer runs the containers).

  • Two-step: POST {analyzer_url}/analyze → detected entities with type, offsets, score; POST {anonymizer_url}/anonymize → transformed text. Entities are configurable (EMAIL_ADDRESS, PHONE_NUMBER, US_SSN, CREDIT_CARD, PERSON, IP_ADDRESS, …). Source: https://microsoft.github.io/presidio/
  • Re-scoped value vs. the built-in pii kind: pii already covers rule/regex detection with mask/block on both hooks incl. streaming. Presidio's increment is (a) NER/ML entities regex cannot express (PERSON, LOCATION, NRP, …), (b) self-hosted compliance posture, and (c) anonymize operatorsreplace, redact, mask, hash — which also close the hash/placeholder action gap tracked in AISIX-Cloud#562.

OpenAI Moderation — free category-based content moderation.

  • API: POST https://api.openai.com/v1/moderations, model omni-moderation-latest. Returns per-category booleans + scores. Source: https://platform.openai.com/docs/guides/moderation
  • Can reuse an existing OpenAI credential the tenant already has. Monitor-before-enforce comes from platform enforcement_mode, not a bespoke flag_only.

3. UI design

Schema-driven: each kind ships a CP descriptor so the dashboard SchemaForm renders it (secret fields blank-on-edit = keep stored ciphertext, same as the existing remote kinds):

  • Lakera (Prompt Injection): api_key (secret), endpoint (default https://api.lakera.ai/v2/guard), optional project id, fail_open, timeout_ms, hook_point (default input).
  • Presidio (PII): analyzer_url, anonymizer_url, entities (multi-select), score threshold, language, action = block | redact (+ operator: replace/mask/hash), hook_point (default both), fail_open, timeout_ms, streaming buffer knobs (same as pii).
  • OpenAI Moderation: api_key (secret), endpoint override (Azure-compatible / mock), model, categories (multi-select) with per-category threshold, fail_open, timeout_ms, hook_point (default input).

4. Implementation approach

Three Guardrail trait impls following the existing aisix-guardrails remote-kind pattern (prompt_shield / text_moderation / aliyun are the templates):

  • Lakera — input hook: call /v2/guard; flaggedBlock{reason} (reason carries detector categories, never matched content — bug: output guardrail error message echoes the matched forbidden literal back to caller #153).
  • OpenAI Moderation — input hook (output optional): any enforced category over threshold → Block. Monitor mode via enforcement_mode.
  • Presidio — input and output: analyze; action=blockBlock; action=redactanonymize and rewrite via redact_input_text / redact_output_text; streaming via BufferFull like pii.
  • Credential storage: same org-scoped encrypted-credential mechanism as Bedrock/ACS. Presidio is self-hosted and needs no vendor secret.

5. Testing & acceptance

Extend the e2e mock service with mock endpoints (Lakera /v2/guard, Presidio /analyze+/anonymize, OpenAI /v1/moderations); point the DP at them via per-kind endpoint override. Real chain end-to-end; mock the external guardrail service only.

Acceptance criteria:

  • Lakera: injection phrase in prompt → 422, upstream skipped; clean prompt → 200
  • OpenAI Moderation: prompt over category threshold → 422; same guardrail with enforcement_mode=monitor → 200 + monitor observation recorded
  • Presidio block: prompt with PII + action=block → 422
  • Presidio input-redact: prompt with PII + action=redact → the request the mock upstream receives is anonymized (assert on the body the upstream saw)
  • Presidio output-redact: response containing PII is anonymized before reaching the caller, non-streaming and streaming (buffer_full)
  • Presidio hash/replace operators: operator config honored in the anonymized text
  • Each kind: schema accepts valid config and rejects missing key / bad endpoint
  • Dashboard CRUD Playwright for each new kind (schema-driven form)
  • fail_open honored on mock 5xx for the remote-API kinds (all three)

6. Docs

api7/docs docs/ai-gateway/traffic-controls/guardrails/: one page per kind (config fields, action semantics, fail-open, monitor-first guidance), wired into sidebars.ai-gateway.js. Paired PR, not in this repo.

Estimate

DP ~1d each = 3d (Presidio closer to 2d with operators + output path), CP 1d, docs 0.5d.

Metadata

Metadata

Assignees

Labels

P1High-value differentiatorcross-repoRequires changes in DP + CP + Dashboard UI + e2edocumentationImprovements or additions to documentationenhancementNew feature or requestgap-with-litellmIdentified by LiteLLM feature parity auditgo

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions