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 viaHL-Project-Id, and maps HiddenLayer v2 outcomes to the TrueFoundry guardrail contract.
Key features on TrueFoundry
- Input validation — blocks prompt injection, jailbreak, and other threats before the model runs (
interaction-evaluations+ inline fallback). - Input mutation — redacts PII and sensitive content in the prompt before it reaches the model (
request-evaluations). - Output validation — blocks threats in the model response using full interaction context.
- Output mutation — redacts sensitive content in the model response (
response-evaluations).
[REDACTED:EMAIL_ADDRESS]).
Architecture
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
| Wrapper rail | HiddenLayer v2 endpoint(s) | Purpose |
|---|---|---|
/validate-input | interaction-evaluations + request-evaluations (fallback) | Block/detect decisions before the model call |
/validate-output | interaction-evaluations + response-evaluations (fallback) | Block/detect decisions on model output |
/redact-input | request-evaluations | Inline pre-model scan; redactions applied in provider payload |
/redact-output | response-evaluations | Inline post-model scan; redactions applied in provider payload |
Enforcement summary
HiddenLayer outcome.action | Validate rail | Mutate rail |
|---|---|---|
NONE | pass (unless inline body was redacted) | pass through unchanged |
DETECT | deny by default | pass through unchanged |
REDACT | deny | apply redacted body (transformed: true) |
BLOCK | deny | deny (HL-Runtime-Action: BLOCK on inline endpoints) |
HIDDENLAYER_ALLOW_DETECT_ON_VALIDATE=true on the wrapper to pass DETECT on validate rails (observe-only policy).
Response contract
| HTTP | Body | Meaning |
|---|---|---|
200 | {"verdict": true} | Allow |
200 | {"verdict": false, "message": "..."} | Block (policy) |
200 | {"verdict": true, "transformed": bool, "result": {...}} | Mutate |
5xx | error JSON | Wrapper or HiddenLayer failure |
verdict: false, not HTTP 4xx.
Wrapper endpoints
| Path | Operation | Target | Hook |
|---|---|---|---|
/validate-input | Validate | Request | llm_input |
/validate-output | Validate | Response | llm_output |
/redact-input | Mutate | Request | llm_input |
/redact-output | Mutate | Response | llm_output |
GET /health — health check. GET /debug/loaded-config — bearer-gated diagnostics (reports whether credentials and project are configured; never returns secret values).
All POST routes expect Authorization: Bearer <WRAPPER_API_KEY> when the key is configured on the wrapper.
Prerequisites
- HiddenLayer OAuth2 credentials —
HIDDENLAYER_CLIENT_IDandHIDDENLAYER_CLIENT_SECRETfrom the AISec Platform Console (API Keys tab). HIDDENLAYER_PROJECT_ID— project ID or alias sent asHL-Project-Idon every detection call. This selects the AISec policy applied to each request.WRAPPER_API_KEY— shared secret; the gateway sends it asAuthorization: Bearer …when calling the wrapper.- Public HTTPS URL for the deployed wrapper.
Setup
Deploy the wrapper
Local: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.Deploy on TrueFoundry (optional)
Deploy on TrueFoundry (optional)
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:Register Custom Guardrail configs
AI Gateway → Guardrails → + Add New Guardrails Group → type Custom.

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
- Group name:
hiddenlayer-guardrails - Add one config per wrapper path (four total), or start with input validate only.
| Field | Value |
|---|---|
| Name | validate-input |
| Description (optional) | Custom guardrail server for validate or mutate via HTTP endpoint |
| Operation | Validate |
| Target | Request |
| Enforcing Strategy | Enforce But Ignore On Error |
| URL | https://<host>/validate-input |
| Headers | Authorization → Bearer <WRAPPER_API_KEY> |
| Config | leave empty when env vars are set on the wrapper |

| Name | Operation | Target | Path |
|---|---|---|---|
validate-output | Validate | Response | /validate-output |
redact-input | Mutate | Request | /redact-input |
redact-output | Mutate | Response | /redact-output |
false (recommended).Attach to traffic
Model pin: AI Gateway → Models → <model> → Guardrails → attach group Add
hiddenlayer-guardrails.Per request — X-TFY-GUARDRAILS header, selector format <group>/<config-name>:redact-input / redact-output configs when you need in-place redaction (Operation: Mutate).Configuration
Environment variables (recommended)
| Variable | Required | Description |
|---|---|---|
HIDDENLAYER_CLIENT_ID | yes | OAuth2 client ID from AISec Console |
HIDDENLAYER_CLIENT_SECRET | yes | OAuth2 client secret |
HIDDENLAYER_PROJECT_ID | yes | HL-Project-Id header (project ID or alias) |
WRAPPER_API_KEY | yes (prod) | Bearer token the TFY gateway sends |
HIDDENLAYER_REGION | no | us (default) or eu |
HIDDENLAYER_PROVIDER | no | Provider in interaction metadata (default: truefoundry) |
HIDDENLAYER_TIMEOUT_SECONDS | no | Per-request timeout (default: 10, clamped 1–60) |
HIDDENLAYER_ALLOW_DETECT_ON_VALIDATE | no | true to pass DETECT on validate rails (default: deny) |
HIDDENLAYER_FAIL_OPEN_ON_UNAVAILABLE | no | true to pass through on HL 5xx (default: fail closed) |
Optional dashboard config JSON
Only needed if you cannot set env vars on the wrapper service. Do not put secrets here in production.
config overrides env defaults when present.
Troubleshooting
401 Unauthorized from the wrapper
401 Unauthorized from the wrapper
Gateway allows despite verdict: false
Gateway allows despite verdict: false
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.DETECT findings block traffic but I want observe-only
DETECT findings block traffic but I want observe-only
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.Validate blocks instead of redacting PII
Validate blocks instead of redacting PII
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.HiddenLayer API unavailable (5xx)
HiddenLayer API unavailable (5xx)
Reference
| Item | Value |
|---|---|
| Source repo | truefoundry/integrations-custom-guardrails/integrations/hiddenlayer |
| HiddenLayer platform | hiddenlayer.com |
| HiddenLayer API (US) | https://api.hiddenlayer.ai/detection/v2/* |
| HiddenLayer API (EU) | https://api.eu.hiddenlayer.ai/detection/v2/* |
| Selector | hiddenlayer-guardrails/<config-name> |