/v1/evaluate before the upstream model call and again on the
response. Every application already routing through the gateway is covered, with no client
changes.
There are two ways to wire it. The native neuraltrust plugin runs inside the gateway, so it
holds the request body and can apply transform — it is the only one of the two that can redact.
The Bring-Your-Own-Guardrails webhook works on any Portkey deployment today, including Portkey
Cloud, but its contract is a boolean, so transform collapses to allow or deny.
This page covers only the Portkey connection. Other gateways: TrustGate, LiteLLM, Kong, Apigee, Azure APIM.
Coverage
Ask — the integration maps the verdict onto a boolean, so an
ask gate is
allowed and recorded. Write the rule as Block if you need a hard stop.
Use it when your apps already reach models through a Portkey config and you want one policy
for all of them.
Not when you do not control the gateway deployment, or you need redaction on streamed
responses — only TrustGate inspects a stream.
Limits. Redaction is conditional twice over: it needs the native plugin, which is not in a
released Portkey version, and on the output side it applies to non-streaming completions only. The
webhook does not redact at all. Tool declarations and tool calls are evaluated where Portkey
populates them and a transformed tool call is written back, but every verdict is request-level: a
block stops the whole request rather than one tool.
Also. deny: true on the hook is what makes a block enforceable. Without it Portkey records
the failed check and returns the request anyway.
Full comparison: Coverage.
Before you start
Keep the policy in Report mode for the first rollout. Report downgrades every rule to
report, so findings appear in Activity without breaking traffic. Switch to Enforce once the
finding volume looks right — see Policies.The native
neuraltrust plugin is contributed in
Portkey-AI/gateway#1772 and is not in a
released Portkey version yet, so it is unavailable on Portkey Cloud. Until it ships, use
the BYOG webhook below, which works on every deployment.1. Enable the plugin
Addneuraltrust to plugins_enabled in the gateway’s conf.json:
conf.json. They go on the check, so one gateway can route
different routes to different collectors.
2. Attach the check to your config
The check id isneuraltrust.evaluate, and it runs on both hooks. Send this as a saved config or
in the x-portkey-config header:
session_id is picked up from request metadata (session_id, or _session_id) when present, so
Activity groups turns the way your application does.
3. Know how each verdict lands
deny is what turns a failed check into enforcement:
transform is written back in the shape the request came in: chat messages, a completion
prompt, or Anthropic messages plus a top-level system. A transformed_payload.input string
redacts the current text instead.
Only choices[0] is scanned and rewritten. Extra completions from n > 1 are left alone, which
matches Portkey’s own shared content helpers.
4. Choose fail-open or fail-closed
This is the setting to read carefully, because the plugin deliberately disagrees with the engine’s default. Portkey treats a check as passing when it returns a verdict or when it errored andfailOnError is not set — and failOnError defaults to false. An unreachable guardrail reported
as an error would therefore be forgiven, and traffic would flow uninspected. So the plugin reports
an unusable verdict as verdict: false with no error attached, which the engine cannot forgive.
Scope is narrow:
fail_open covers only connect errors, timeouts, and HTTP 502/504. Everything
else fails closed even when you asked for fail_open:
- HTTP 401/403, and HTTP 503 entitlement failures
- any other 4xx or 5xx, including 429
- a
200that is not JSON, or that carries an unknown verdict - a
transformed_payloadthat cannot be applied safely - a missing
apiKey, and any unexpected error inside the plugin
5. Verify
A block is visible from the HTTP response, so one call is the whole check:446 and the reason under hook_results:
trace_id is the same identifier the finding carries in Activity, so use it to reconcile
a request with what the console shows. If a blocking prompt returns 200, check that the hook
sets deny: true and that the policy is in Enforce rather than Report. A 446 whose explanation
reads TrustGuard authentication failed is the fail-closed path, not a policy decision — the key
is wrong.
Streaming responses
The after-request hook receives no parsed body on a streamed response. The plugin returns a pass without calling TrustGuard rather than evaluating nothing and reporting a verdict it did not get. For coverage on the response, either disable streaming on the routes that need it, or put TrustGate in front — it is the only collector that buffers and inspects a stream.Before the native plugin ships
Until a Portkey release carriesneuraltrust.evaluate, the same connection is available as a
Bring-Your-Own-Guardrails webhook, which needs no gateway build and works on Portkey Cloud.
- Create an API key on the collector.
- In Portkey, add a Guardrail Webhook check aimed at the evaluate URL.
- Attach it under
before_request_hooks/after_request_hookswithdeny: true. - Map Portkey user and trace metadata to
consumer_idandsession_id.
Limits to keep in mind
- Only traffic through the gateway is inspected. Anything calling a provider directly bypasses TrustGuard, so the network path has to make the gateway the only way out.
- The check runs on chat completions, text completions and Anthropic Messages. Embeddings and any request type the plugin does not recognise are treated as nothing to check and pass through.
- Each guarded direction costs one round trip, so a turn with both hooks is two. Keep
timeouttight enough that a stalled call cannot hold a request open. - The gateway sends
session_idfrom request metadata but does not derive aconsumer_id, so Activity groups by conversation rather than by virtual key.