Skip to main content
LiteLLM is an open-source proxy that puts one OpenAI-compatible API in front of many model providers. A custom guardrail file referenced from config.yaml calls POST /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 file implements apply_guardrail and a streaming hook. With incremental_diff, it buffers the chat completion, applies the policy, and returns the inspected response in streaming format. You do not run a second HTTP service Traffic sent directly to a provider bypasses this integration. It also does not see local agent actions such as shell commands or MCP tools on a developer machine. For those, use a client integration such as Cursor or Claude Code.

Integration capabilities

The proxy can also carry the conversation, so policy applies across turns rather than to one message at a time. That requires the caller to send a session key. See Multi-turn conversations.

Before you start

Create the policy in Observe mode. Observe records decisions in Activity without enforcing them. Review the results, then switch the policy to Enforce. See Policies.

Set up the custom guardrail file

The guardrail uses the httpx client included with LiteLLM, so it requires no additional dependency.

Mount it and declare it

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). Then declare it:
TRUSTGUARD_API_BASE is the host (https://trustguard.neuraltrust.ai or your workspace URL). The file appends /v1/evaluate. A value that already includes that path still works. mode must list both pre_call and post_call for Input and Output coverage. default_on: true applies the guardrail when a request does not name it.

Ordinary completions vs streamed completions

Use the same file and the same config.yaml for both shapes of traffic. The recommended configuration above buffers streamed output until inspection finishes, including when a policy rewrites tool arguments. A normal request sends the prompt, then the complete answer. With streamed block_only, LiteLLM inspects accumulated output during generation. With incremental_diff, the custom hook inspects the complete answer once before returning any output Use this when the client must receive only inspected output:
The custom hook collects the complete OpenAI-style chat stream and uses LiteLLM’s non-streaming response translator to apply the verdict before converting the result back to a streaming chunk. This avoids releasing partial identifiers before a detector recognizes them, and prevents tool-call deltas from bypassing inspection in released LiteLLM The client still receives the streaming response format, but waits for the full answer. This mode supports /v1/chat/completions; it does not provide buffered output protection for other streaming API formats. Tool results are inspected when the caller includes them as role: "tool" messages in its next request. The connector does not execute or intercept local tools The example explicitly selects incremental_diff. Omitting the setting falls back to block_only for compatibility. It provides no guarantee that output is inspected before delivery, and output transformations are discarded

Multi-turn conversations

A multi-turn attack spreads its intent across several messages. Each one reads as harmless on its own. See multi-turn attacks. Two inputs give TrustGuard the conversation: Neither happens by default. /v1/evaluate synthesizes a session_id when the field is omitted, so a proxy whose callers send no conversation key produces one session per request.

Send a session ID

LiteLLM does not invent a conversation key. The caller supplies one on every request. A header always overrides a body value.
metadata: {"litellm_session_id": "…"} does not work. Inside metadata the key is session_id.
Chat clients that resend the transcript already put earlier turns in messages. The guardrail forwards what LiteLLM extracted. Tool results must keep role: "tool" so indirect prompt injection can see them. On /v1/responses, send x-litellm-session-id explicitly. previous_response_id does not supply a session key to the guardrail.

Verify

Assign an Enforce policy with a Block rule that matches the test prompt:
Expect HTTP 400 with error: "Blocked by TrustGuard" and a trace_id. Use that id in Activity. To verify transform, enable a DLP rule and send an email in the prompt. Expect HTTP 200 and a masked value. To verify streamed redaction, add "stream": true after setting streaming_transform_mode: incremental_diff.

Reference

Coverage

Output redaction on stream: true needs streaming_transform_mode: incremental_diff. Tool content is covered when LiteLLM includes it in the extracted messages. Enforcement is request-level: a finding blocks the complete LiteLLM request.

What is evaluated

Verdict handling

Configuration

Failure behavior. Connection errors, timeouts, and every non-200 follow fail_open:
fail_open: true applies to every non-200 response, including 401, 403, and 429. Monitor the TrustGuard unreachable, failing open warning if you enable it.

Attributes

  • session_id: the conversation key the caller supplied. See Multi-turn conversations.
  • consumer_id: the virtual key’s alias, then user email, user id, or team alias. The master key resolves to LiteLLM’s proxy admin user id, default_user_id. A key with none of those fields sends no consumer_id.

Troubleshooting