Skip to main content
If you already run a LiteLLM proxy, you make it a TrustGuard collector by loading one custom guardrail that calls /v1/evaluate before the upstream model call and again on the response. Every application already pointing at the proxy is covered, with no client changes. The guardrail is what enforces the verdict: TrustGuard always answers 200 and the caller decides what to do with status. This page covers only that connection — see Gateway integrations for the other gateways.

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.

1. Add the guardrail

Create trustguard_guardrail.py. It uses the httpx client that ships inside LiteLLM, so your proxy image needs no extra dependency.

2. Load it in the proxy

trustguard_guardrail.TrustGuard is resolved relative to the directory the proxy runs from, so the file has to sit next to your config.yaml/app in the official image. Mount it read-only as a volume, ship it as a ConfigMap with subPath, or bake it into your image. Then declare the guardrail:
mode carries the two directions: pre_call runs before the upstream request and maps to direction: input, post_call runs on the response and maps to direction: output. Declaring only one of them leaves that phase of your policy unused. default_on: true applies the guardrail to every request — without it callers opt in per request, which is not an access control worth relying on. Set TRUSTGUARD_API_BASE to {TRUSTGUARD_URL}/v1/evaluate and inject TRUSTGUARD_API_KEY from your secret manager. Then restart the proxy.

3. Choose fail-open or fail-closed

fail_open decides what happens when TrustGuard cannot be reached — a timeout, DNS failure, or a non-200. It is separate from what happens when an individual detector errors, which is a deployment setting on TrustGuard itself.
fail_open: true means an outage of the guardrail silently becomes an outage of your controls rather than of your service. If you choose it for availability reasons, alert on the failing open (traffic NOT inspected) log line — otherwise nobody will notice.

4. Choose what gets inspected

An agent client — an IDE assistant or an in-house agent loop — resends the entire transcript on every turn, including the system prompt and every earlier tool result. That makes scope a design decision rather than a tuning detail. Two details matter either way. Tool results must keep role: "tool", because the indirect prompt injection detector scopes itself to that role — flattening every message to user disables it. And an agent transcript routinely carries hundreds of kilobytes, so measure the added latency against a realistic transcript rather than a one-line prompt.

5. Verify

Set LITELLM_LOG=INFO on the proxy first, otherwise the guardrail’s own lines are suppressed and you cannot see which verdict came back. A normal request should log status=allow in both directions and return 200. Then check that enforcement actually happens:
The second request logs a pair like this — the jailbreak logs status=block instead, and no output line, because the model is never called:
Every request that reaches the model logs an input line followed by an output line. If you only ever see input, post_call is missing from mode. The trace_id is the same identifier the finding carries in Activity, so use it to reconcile a request with what the console shows.

Streaming responses

With stream: true — what interactive clients and IDE assistants use — LiteLLM runs the post-call guardrail on the assembled response after the chunks have already been sent. Its own source describes that path as audit-only, content has already been delivered to the client.
On streamed responses, an output-side block or transform is detection after the fact, not prevention: the user has already seen the text. Input-side enforcement is unaffected and still happens before the model is called.
For preventive enforcement on the response, either disable streaming on the routes that require it, or implement async_post_call_streaming_iterator_hook and buffer chunks until a verdict is available — at the cost of the time-to-first-token that streaming exists to provide.

Limits to keep in mind

  • Only traffic through the proxy is inspected. Anything calling a provider directly bypasses TrustGuard, so the network path has to make the proxy the only way out.
  • The guardrail runs on chat-style requests. Embeddings, image, and audio routes need their own handling.
  • Each turn costs two round trips to TrustGuard, so keep timeout tight enough that a stalled call cannot hold a request open.
The trustguard-sdk package is an alternative to the raw HTTP calls above, documented in Application integrations. It adds a dependency to the proxy image, which is why this page uses the bundled HTTP client instead.