verdict; the adapter sends the relevant request or response content to
POST /v1/evaluate and maps TrustGuard’s status
to that verdict.
Only traffic routed through a Portkey configuration is evaluated. Direct calls
to a model provider bypass this integration.
Integration capabilities
Policy can also apply across the turns of a conversation rather than to one
message at a time, which requires the caller to send a session key — see
Group the turns of a conversation.
Before you start
Start with the policy in Observe mode. Findings appear in Activity without
affecting traffic. Switch to Enforce after reviewing the results. See
Policies.
1. Implement the webhook adapter
Portkey sends a JSON object containingrequest, response, metadata, and
eventType. For beforeRequestHook, evaluate request.json as input. For
afterRequestHook, evaluate response.json as output. Use the corresponding
text field when a normalized JSON body is not available.
The following function shows the contract conversion. Deploy the equivalent in
your webhook service and return its result as JSON:
request.json as payload is what puts the caller’s whole messages
array in front of the policy, so the evaluation is not limited to the newest
message. See
Group the turns of a conversation.
Do not point default.webhook directly at /v1/evaluate. Portkey’s hook event
contains top-level fields that the Evaluate API does not accept, and the
Evaluate API returns status rather than Portkey’s required verdict.
The sample maps only block to verdict: false. It allows allow, report,
ask, and transform. It does not return transformedData, so redaction is not
supported. Use Block rules for enforcement.
2. Configure the BYOG hooks
Adddefault.webhook to both hook phases. Replace the example adapter URL and
token with your values:
deny: true makes a failed check return HTTP 446. async: false keeps the
check in the request path so Portkey can enforce its result. With only the
before-request hook, Output-phase rules do not run.
Prefer a saved Portkey configuration when the webhook header contains a secret.
An inline configuration sent through x-portkey-config exposes that value to
the calling application.
3. Group the turns of a conversation
A multi-turn attack spreads its intent across several messages. Each one reads as harmless on its own; the escalation, the reinforcement, or the reassembled instruction exists only across turns. See multi-turn attacks for the techniques involved — Crescendo, Echo Chamber, Multi-Turn Manipulation, and Payload Splitting. Their common target is a check that inspects each message independently, which is what the adapter does until you give it the conversation. Two inputs give TrustGuard the conversation, and they are complementary rather than alternatives:
Neither happens by default.
/v1/evaluate
synthesizes a session_id when the field is omitted,
so a gateway whose callers send no conversation key produces one session per
request. Nothing errors and no finding goes missing, so the gap is only visible
as single-turn conversations in Activity.
Send a session ID through metadata
Portkey has no conversation identifier of its own, so the caller — or, better, an authenticated proxy in front of Portkey — supplies one on every request:event.metadata, on both hook
phases. _user is Portkey’s reserved user identifier, and session_id is the
key its own metadata guidance recommends for grouping related requests, though
the gateway itself does nothing with it: only your adapter reads it.
The adapter maps both onto the Evaluate API body, as shown in
step 1. It coerces each to a string because
Portkey parses the header without validating value types, so a caller can put a
number where a string is expected.
Do not reuse x-portkey-trace-id as the conversation key. Portkey generates one
per request when the caller omits it, it identifies a request rather than a
conversation, and it does not reach the webhook body at all.
Give one call the history
Portkey does not store turns, but it does not need to:event.request.json is
the request body as Portkey parsed it, so on a /v1/chat/completions call it
already holds the caller’s complete messages array. Forwarding it as payload
— which the step 1 adapter does — puts the
whole conversation in one evaluation call at no extra cost.
The transcript grows every turn, so account for the payload size in the webhook
timeout and in your token budget.
The afterRequestHook event carries request.json alongside response.json, so
an adapter can send the transcript and the completion together on the output leg
rather than the completion alone. The sample sends only the completion, which is
the smaller payload; send both if an Output-phase rule needs to judge the answer
against the conversation that produced it.
4. Configure failure behavior
Portkey’s webhook timeout defaults to 3000 ms. The example raises it to 5000 ms and setsfailOnError: true, so a timeout or non-200 adapter response fails the
check. With deny: true, Portkey returns 446 instead of calling the provider or
returning the completion.
Without failOnError: true, Portkey allows the request when the webhook times
out or returns an error. Use that setting only when you deliberately want to
fail open.
The adapter should return a non-200 response when TrustGuard is unavailable or
rejects its credentials. Returning { "verdict": true } in those cases makes
the integration fail open regardless of the Portkey setting.
5. Verify
Attach the configuration to a request using your existing Portkey client or thex-portkey-config header. With a blocking rule in Enforce mode:
- Send a prompt that triggers the rule.
- Confirm that Portkey returns HTTP 446 and that
hook_resultscontains thetrustguard-inputhook anddefault.webhookcheck. - Confirm that the adapter’s
dataappears under the check’sresponseData, including the TrustGuardtrace_id. - Find the same
trace_idin TrustGuard Activity under the expectedconsumer_idandsession_id.
Reference
Coverage
The adapter evaluates Portkey’s normalized request or response body. Tool
definitions and model-selected tool calls are available only when Portkey
includes them in that body, and a block stops the complete request or response,
not an individual tool event. The adapter does not apply transformed payloads.
Portkey does not support blocking output guardrails on streamed responses, so
use non-streaming responses when output enforcement is required.
Have the adapter skip its TrustGuard call on the response leg of a streamed
request, using
event.request.isStreamingRequest or
event.request.json.stream. Portkey can still invoke the after-request hook on a
stream, with no assembled response body to inspect. An adapter that evaluates it
anyway posts an empty output payload under a real session_id on every streamed
turn, which pollutes the conversation grouping it is trying to establish.
A turn with both synchronous hooks makes two TrustGuard evaluations. Each hook
also passes through the adapter, so include both network legs in the timeout and
latency budget.
What is evaluated
Configuration
Attributes
consumer_id: map it from the_uservalue in verified Portkey metadata. Per-consumer policy routing and gates matchingconsumer.iddepend on this value.session_id: map it from a stable, verifiedsession_idvalue in Portkey metadata, on both hook phases. Without it,/v1/evaluatesynthesizes a session per request, which breaks the grouping the stateful detectors rely on. See Group the turns of a conversation.attributes.model.nameandattributes.model.provider: the adapter can read these fromrequest.json.modeland Portkey’sproviderfield.trace_idandrequest_id: return them in the webhook response’sdataobject. Portkey records that object underhook_results[].checks[].data.responseData.
Troubleshooting
Related
- Evaluate API: request and response contract for the adapter
- Policies: Observe and Enforce modes
- Collectors: collector keys and policy assignment
- Portkey BYOG webhooks: webhook request, response, and failure behavior
- Portkey metadata: supported metadata keys and precedence
Experimental: a native
neuraltrust plugin is proposed in
Portkey-AI/gateway#1772, but
it is not part of a released Portkey version.