> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neuraltrust.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway integrations

> Run TrustGuard behind an AI gateway — TrustGate (first-class), Portkey, LiteLLM, Kong, Apigee, or Azure APIM — with the exact configuration each uses.

Running TrustGuard behind a gateway is the lowest-friction deployment: the gateway is
already in the request/response path, so it calls [`/v1/evaluate`](/trustguard/api/evaluate) and
enforces the verdict for **every** model call with no application changes.

Every gateway integration starts the same way: **create an API key on the collector**,
then wire the gateway to call the guard endpoint and enforce the response `status`: **block** → deny; **transform** → forward `transformed_payload`; **report** / **allow** → forward (log on report).

## TrustGate (recommended)

[TrustGate](/trustgate/overview) is NeuralTrust's own AI gateway and the
first-class collector — findings appear as first-class spans in TrustGate traces, across
LLM, MCP, and A2A traffic.

1. Create an API key on the collector.
2. Open your TrustGate gateway configuration.
3. Enable the **TrustGuard policy** on the routes you want to protect and paste the API
   key into its settings.
4. Send a test request — it appears in TrustGuard's **Activity** page within seconds.

## Portkey

Portkey calls TrustGuard through a **Bring-Your-Own-Guardrails** webhook check on requests
and responses.

<Warning>
  Portkey expects `{ verdict }`. Without a thin adapter that maps TrustGuard `status` → `verdict` (e.g. `verdict = status != "block"`, and apply `transformed_payload` on transform), Portkey **will not enforce** TrustGuard decisions.
</Warning>

1. Create an API key on the collector.
2. In Portkey, create a Guardrail with a **Webhook** check pointing at the guard endpoint.
3. Add it to `input_guardrails` / `output_guardrails` in your Portkey Config with
   `deny: true` to enforce.
4. Portkey expects a `{ verdict }` response — map `verdict = (status != "block")` with a
   thin adapter if your plan doesn't support response mapping. Map Portkey request metadata
   (user, trace id) to `consumer_id` and `session_id`.

```json theme={null}
{
  "input_guardrails": [{
    "default.webhook": {
      "webhookURL": "{TRUSTGUARD_URL}/v1/evaluate",
      "headers": { "Authorization": "Bearer <collector-api-key>" }
    },
    "deny": true
  }]
}
```

## LiteLLM

Add TrustGuard as a LiteLLM **custom guardrail** that calls the guard endpoint on every
request.

1. Create an API key on the collector.
2. Create `trustguard_guardrail.py`: a `CustomGuardrail` subclass that calls TrustGuard via
   the Python SDK (`pip install neuraltrust-trustguard`) and raises when `is_blocked` is
   true. Set `consumer_id` from the LiteLLM user/key alias and `session_id` from
   `litellm_session_id`.
3. Reference the class from your proxy `config.yaml`.
4. Restart your LiteLLM proxy.

```yaml theme={null}
guardrails:
  - guardrail_name: trustguard
    litellm_params:
      guardrail: trustguard_guardrail.TrustGuard
      mode: [pre_call, post_call]
      api_base: {TRUSTGUARD_URL}/v1/evaluate
      api_key: <collector-api-key>
      default_on: true
```

## Kong

Use Kong's **`ai-custom-guardrail`** plugin (requires AI Proxy) to send prompts and
completions to the guard endpoint.

1. Create an API key on the collector.
2. Configure the **AI Proxy** (or AI Proxy Advanced) plugin on your route.
3. Add the **`ai-custom-guardrail`** plugin pointing at the guard endpoint. Include
   `consumer_id` (Kong's `X-Consumer-ID`) and `session_id` in the body template.
4. Apply the config — requests are blocked when TrustGuard returns `status: "block"`.

```yaml theme={null}
plugins:
  - name: ai-custom-guardrail
    config:
      guarding_mode: BOTH
      text_source: concatenate_all_content
      params:
        api_key: "<collector-api-key>"
      request:
        url: {TRUSTGUARD_URL}/v1/evaluate
        headers:
          Authorization: Bearer $(conf.params.api_key)
        body:
          protocol: llm
          direction: input
          payload:
            input: "$(content)"
      response:
        block: "$(check_response.block)"
        block_message: "$(check_response.block_message)"
      functions:
        check_response: |
          return function(resp)
            -- resp.transformed_payload holds masked content when status == "transform";
            -- this plugin's response mapping only supports block/block_message, so
            -- rewriting the body for Transform rules needs a downstream plugin.
            return {
              block = resp.status == "block",
              block_message = "Blocked by TrustGuard"
            }
          end
```

## Apigee

Call the guard endpoint from a **Shared Flow** and raise a fault when a request is blocked.

1. Create an API key on the collector.
2. Create a Shared Flow with an **AssignMessage** policy that builds the request body
   (`{ protocol, direction, payload, consumer_id, session_id }`) — use the client\_id /
   developer app as `consumer_id`.
3. Add a **ServiceCallout** policy that POSTs it to the guard endpoint with the
   `Authorization: Bearer` header.
4. Add a **RaiseFault** policy (403) conditioned on `status == "block"`.
5. Attach the Shared Flow to your proxies with a FlowCallout.

## Azure APIM

Call the guard endpoint with a **`send-request`** policy and block requests before
they reach your backend.

1. Create an API key on the collector.
2. Open your API in the Azure portal.
3. Add a `send-request` policy in the **inbound** section posting the prompt to the guard
   endpoint.
4. Return 403 when the response `status` is `"block"`; rewrite the body with
   `transformed_payload` when `status` is `"transform"`; repeat in **outbound** for
   completions.

```xml theme={null}
<inbound>
  <send-request mode="new" response-variable-name="guard" timeout="10">
    <set-url>{TRUSTGUARD_URL}/v1/evaluate</set-url>
    <set-method>POST</set-method>
    <set-header name="Authorization" exists-action="override">
      <value>Bearer <collector-api-key></value>
    </set-header>
    <set-body>@(JsonConvert.SerializeObject(new {
      protocol = "llm",
      direction = "input",
      payload = new { input = context.Request.Body.As<string>(preserveContent: true) },
      consumer_id = context.Subscription?.Id ?? "",
      session_id = context.Request.Headers.GetValueOrDefault("X-Session-Id", "")
    }))</set-body>
  </send-request>
  <choose>
    <when condition="@(((IResponse)context.Variables["guard"]).Body.As<JObject>()["status"].Value<string>() == "block")">
      <return-response>
        <set-status code="403" reason="Blocked by TrustGuard" />
      </return-response>
    </when>
    <when condition="@(((IResponse)context.Variables["guard"]).Body.As<JObject>()["status"].Value<string>() == "transform")">
      <!-- Masked/rewritten content — forward transformed_payload instead of the original body -->
      <set-body>@(((IResponse)context.Variables["guard"]).Body.As<JObject>()["transformed_payload"]["input"].Value<string>())</set-body>
    </when>
    <!-- "report" / "allow" fall through and forward the original request unchanged -->
  </choose>
</inbound>
```
