Skip to main content
Deploy the integrations/hiddenlayer FastAPI wrapper on any public HTTPS host — TrueFoundry, Docker, Render, ECS, Cloud Run, or on-prem. The gateway calls it at llm_input / llm_output via the Custom Guardrail contract; the wrapper forwards traffic to HiddenLayer AIDR Detection v2 and returns verdict JSON on HTTP 200.
Source repository: truefoundry/integrations-custom-guardrails/integrations/hiddenlayer/. It contains the Dockerfile, deploy script, and tests referenced below. No v1 APIs are used — all traffic goes to /detection/v2/* endpoints only.

What is HiddenLayer?

HiddenLayer AISec is a runtime security platform for LLM applications. Policies are defined in the AISec Console; the wrapper does not embed policy logic. It authenticates with OAuth2 client credentials, scopes every call to your project via HL-Project-Id, and maps HiddenLayer v2 outcomes to the TrueFoundry guardrail contract.

Key features on TrueFoundry

  1. Input validation — blocks prompt injection, jailbreak, and other threats before the model runs (interaction-evaluations + inline fallback).
  2. Input mutation — redacts PII and sensitive content in the prompt before it reaches the model (request-evaluations).
  3. Output validation — blocks threats in the model response using full interaction context.
  4. Output mutation — redacts sensitive content in the model response (response-evaluations).
Wire validate rails for hard stops. Add mutate rails when you need redacted text forwarded to the model or caller (tokens like [REDACTED:EMAIL_ADDRESS]).

Architecture

The wrapper always returns HTTP 200 and signals the policy decision in the JSON body. Infrastructure failures return HTTP 5xx. See Custom guardrail response contract.

HiddenLayer v2 API mapping

Enforcement summary

Set HIDDENLAYER_ALLOW_DETECT_ON_VALIDATE=true on the wrapper to pass DETECT on validate rails (observe-only policy).

Response contract

Policy blocks use 2xx + verdict: false, not HTTP 4xx.

Wrapper endpoints

GET /health — health check (no auth). GET /debug/loaded-config — bearer-gated diagnostics (reports whether credentials and project are configured; never returns secret values). All POST routes require Authorization: Bearer <WRAPPER_API_KEY>. If WRAPPER_API_KEY is missing, empty, or still the example placeholder, every guardrail route returns HTTP 503 (fail closed on misconfiguration). For local dev without a key, set ALLOW_NO_AUTH=true — never use that in production.

Prerequisites

  • HiddenLayer OAuth2 credentialsHIDDENLAYER_CLIENT_ID and HIDDENLAYER_CLIENT_SECRET from the AISec Platform Console (API Keys tab).
  • HIDDENLAYER_PROJECT_ID — project ID or alias sent as HL-Project-Id on every detection call. This selects the AISec policy applied to each request.
  • WRAPPER_API_KEY — shared secret; the gateway sends it as Authorization: Bearer … when calling the wrapper.
  • Public HTTPS URL for the deployed wrapper.
HiddenLayer credentials, project ID, region, and API/auth base URLs are resolved only from service environment variables — the per-request dashboard config JSON cannot override them (prevents SSRF and credential exfiltration). Do not put secrets in the TFY dashboard config field or in client requests. Never deploy without a real WRAPPER_API_KEY; do not set ALLOW_NO_AUTH or HIDDENLAYER_SKIP_PROJECT_ID_CHECK in production.

Setup

1

Clone and configure

.env
EU tenants: set HIDDENLAYER_REGION=eu (uses api.eu.hiddenlayer.ai / auth.eu.hiddenlayer.ai).
2

Deploy the wrapper

Local:
Set WRAPPER_API_KEY in .env before testing guardrail routes. Alternatively, add ALLOW_NO_AUTH=true for keyless local dev only.Smoke test:
Docker or any cloud host:Build and run the container on ECS, Cloud Run, Kubernetes, Render, or any platform with a public HTTPS URL. Put TLS in front of the service; the gateway must reach paths such as https://<host>/validate-input.
Set TFY_WORKSPACE_FQN, TFY_PUBLIC_HOST, TFY_PUBLIC_PATH, and secret FQNs in .env. Create secrets hiddenlayer-client-id, hiddenlayer-client-secret, and wrapper-api-key under group hiddenlayer-guardrails-tfy in Platform → Secrets, then:
3

Register Custom Guardrail configs

AI Gateway → Guardrails → + Add New Guardrails Group → type Custom.
  • Group name: hiddenlayer-guardrails
  • Add one config per wrapper path (four total), or start with input validate only.
Input validate example:
TrueFoundry custom guardrail form: Validate, Request target, /validate-input URL, Authorization Bearer header

HiddenLayer Custom Guardrail configuration (input validate)

Register the remaining configs:Auth Data → Custom Bearer Auth works the same as Headers if you prefer not to set headers manually. Set Fail on error to false (recommended).
4

Attach to traffic

Model pin: AI Gateway → Models → <model> → Guardrails → attach group hiddenlayer-guardrails.Per requestX-TFY-GUARDRAILS header, selector format <group>/<config-name>:
Add redact-input / redact-output configs when you need in-place redaction (Operation: Mutate).
5

Verify

Call the wrapper directly:
Confirm credentials and project are configured (no secret values are returned).

Configuration

EU tenants: set HIDDENLAYER_REGION=eu (uses api.eu.hiddenlayer.ai / auth.eu.hiddenlayer.ai).

Advanced / local-dev variables

When both env and per-request config set outage behavior, HIDDENLAYER_FAIL_OPEN_ON_UNAVAILABLE on the service wins over dashboard config.

Optional dashboard config JSON

Optional per-request overrides for metadata and policy knobs. Credentials, project ID, region, and API hosts must stay in service env vars — they cannot be set here.
Per-request config overrides env defaults for these fields when present, except HIDDENLAYER_FAIL_OPEN_ON_UNAVAILABLE which takes precedence over fail_open_on_unavailable in config.

Troubleshooting

Guardrail routes return HTTP 503 when WRAPPER_API_KEY is missing, empty, or still the example placeholder. Set a strong key on the service, or ALLOW_NO_AUTH=true for local dev only. Check GET /debug/loaded-configwrapper_auth_enabled should be true in production.
The Authorization: Bearer … value the gateway sends doesn’t match the wrapper’s WRAPPER_API_KEY env var. Three places must agree:
  1. The secret or env var on the deployed wrapper.
  2. The Custom Guardrail Config’s Headers or Auth Data → Custom Bearer Auth field value.
  3. Any platform secret FQN referenced at deploy time.
The wrapper signals rail decisions via {"verdict": false} on HTTP 200. Confirm by curling the wrapper directly — if you get 200 + {"verdict": false} but the gateway still returns a completion, the gateway is the issue.Workaround: switch the Custom Guardrail Configs’ Enforcing Strategy to Enforce. See Enforcing Strategy.
Set HIDDENLAYER_ALLOW_DETECT_ON_VALIDATE=true on the wrapper, or "allow_detect_on_validate": true in dashboard config. Validate rails will pass DETECT outcomes; REDACT and BLOCK still deny.
Use /redact-input and /redact-output rails with Operation: Mutate instead of validate rails. Validate rails deny on REDACT; mutate rails apply the redacted body.
Check wrapper logs for upstream errors. By default the wrapper fails open on HiddenLayer 5xx/timeout — traffic passes unscanned and returns {"verdict": true}. With dashboard Fail on error: false, the gateway also allows the LLM call when the wrapper returns 5xx.For safety-critical rails, set HIDDENLAYER_FAIL_OPEN_ON_UNAVAILABLE=false on the service or "fail_open_on_unavailable": false in dashboard config (env wins if both are set). That blocks traffic when HiddenLayer is unavailable.

Reference