Overview
Fiddler implements the LiteLLM Generic Guardrail API spec, allowing you to plug Fiddler’s guardrails directly into a LiteLLM proxy gateway. Once configured, every LLM request routed through the proxy is checked by Fiddler — in the recommendedpre_call mode, before it ever reaches the model.
This page takes you from a clean LiteLLM installation to a verified block, redact, and allow decision in about ten minutes.
Pick your path before you start:
The configuration on this page checks for:
- Secrets — API keys, tokens, credentials, and connection strings
- PII — personally identifiable information (emails, phone numbers, SSNs, credit cards, etc.)
How It Works
Prerequisites
Before you start, you need:- A Fiddler environment with Guardrails enabled.
Your instance base URL (for example
https://your-company.fiddler.ai) is theapi_baseprefix. If the endpoint returns HTTP 403, Guardrails is not enabled for your deployment — contact Fiddler. - A Fiddler API key, created under Settings → Credentials.
- LiteLLM ≥ 1.91.0 (this page was verified against LiteLLM 1.96.2).
- An LLM provider API key — the quick start uses OpenAI.
- uv installed, or another way to run the LiteLLM proxy.
- Network access from the proxy host to your Fiddler instance and your LLM provider, over HTTPS.
Quick Start
1
Set Environment Variables
FIDDLER_AUTH_HEADER exists because the config below references it with os.environ/FIDDLER_AUTH_HEADER —
the key stays in your environment and never appears in the config file.2
Create a Minimal config.yaml
/beta/litellm_basic_guardrail_api to api_base automatically.
The full endpoint called is https://<your-fiddler-instance>/v3/guardrails/litellm/beta/litellm_basic_guardrail_api.3
Start LiteLLM
"fastapi<0.140.7" pin works around a LiteLLM 1.96.x dependency gap:
its declared FastAPI range admits versions that removed an internal import the proxy still uses,
so an unpinned install fails at startup with ImportError: cannot import name 'get_flat_dependant'.
Remove the pin once upstream ships a fix.
To run the proxy in Docker instead, see the
LiteLLM Docker guide —
the guardrails configuration above is identical.4
Verify Block, Redact, and Allow
1. A synthetic secret is blocked. Secrets use Expected response — HTTP 400 with the guardrail’s reason:2. Synthetic PII is redacted in place. PII uses Expected: HTTP 200 and a normal model response.
The redaction happens between the proxy and the model, so to see it directly,
call the Fiddler endpoint with the same text:Expected response — the exact sanitized text the model would receive:3. Benign traffic passes through. Ordinary requests reach the model unchanged:Expected: HTTP 200 with a normal completion (for example, “The capital of France is Paris.”).You now have a working guardrail: secrets are blocked with HTTP 400,
PII is redacted before the model sees it, and clean traffic is unaffected.
mode: block, so the request never reaches the model:mode: redact, so the request succeeds
and the model receives sanitized text:What This Configuration Enables
The quick-start configuration runs exactly two checks on every request, before the LLM call:
Check selection is explicit: only the checks you list with
enabled: true run.
If you omit additional_provider_specific_params entirely, server-side defaults apply instead.
Always configure checks explicitly so the behavior matches this page.
The three failure controls in the config are also explicit, even where they match the default,
so that a secure posture survives upstream default changes:
See Failure Behavior for what each control covers and how they compose.
What Gets Scanned
- Free-text messages — user, assistant, and system message text forwarded by LiteLLM in
texts[]. Withmode: redact, detected values are replaced in place (for example[REDACTED EMAIL]). - Tool-call arguments — structured JSON in
tool_calls[].function.arguments. Detections always block, because redacting inside structured JSON is unsafe — see Tool Call Handling.
texts and tool_calls[].function.arguments are scanned.
Other request fields (tool definitions, images, headers, metadata) are accepted for protocol
compatibility but never scanned — see the API Reference.
Supported Modes and Endpoints
Fiddler supports all three LiteLLM guardrail modes. Setmode in your proxy config to one or more of:
during_call hides guardrail latency behind the LLM round-trip:
the response is held until the check completes,
but because the LLM call has already started, the input cannot be modified.
Use it only when block-or-allow is sufficient.
You can combine modes. For example, mode: [pre_call, post_call] scans both input and output:
Supported Endpoints
The guardrail runs on LiteLLM proxy endpoints that carry text content, including/v1/chat/completions (OpenAI format) and /v1/messages (Anthropic format).
LiteLLM extracts text from the request and forwards it to the Fiddler endpoint
regardless of the upstream provider format,
and applies redacted text before the provider call on both endpoint families.
Per-Request Control
Withdefault_on: true (the quick-start configuration), the guardrail runs on every request automatically.
When default_on is omitted, LiteLLM treats it as false, so set it explicitly.
Selective Activation
Setdefault_on: false in the proxy config,
then activate the guardrail on individual requests by passing guardrails in the request body:
"guardrails": ["fiddler"] bypass the guardrail entirely —
the Fiddler endpoint is never called.
Check Reference
Each check is configured entirely in the LiteLLM proxy’sadditional_provider_specific_params:
enabled(true/false) — whether the check runs at all.mode(redact/block) — what happens on a detection. The default isredactfor both checks.thresholdandentities(PII only) — detection sensitivity and entity selection.
Secrets
Detects credentials, API keys, and tokens.PII
Detects personally identifiable information.entities switches the check to exactly the entities you list — it replaces the default set
rather than extending it.
For the available entity types, see the PII Detection tutorial.
Detection is confidence-based:
values below threshold are left untouched,
so entities like personal names may pass through at the default threshold
while high-precision entities like emails and phone numbers redact reliably.
Failure Behavior
Three settings control what happens when a guardrail check cannot complete. Two belong to LiteLLM and one to Fiddler, and each observes a different class of failure.How the LiteLLM Controls Compose
LiteLLM lets a failed guardrail call through when either condition holds: the failure is in the unreachable class andunreachable_fallback: fail_open,
or fail_on_error: false.
There is no conflict case — fail-open wins if either setting grants it.
In practice:
- With the quick-start values (
fail_closed+true), every guardrail call failure rejects the request. unreachable_fallback: fail_openwithfail_on_error: truetolerates outages (unreachable endpoint, gateway 502/503/504) while still rejecting on malformed responses and other non-2xx errors.fail_on_error: falselets every guardrail failure through, regardless ofunreachable_fallback— it is the broadest bypass and deserves deliberate consideration.
fail_on_error: false cannot override a valid decision:
a successfully parsed action: BLOCKED response always blocks.
What the Client Sees
A blocked request is a 400 for non-streaming calls and for a pre_call block on a streaming call — the
check runs before generation starts, so “before the first chunk” is trivially true there. It does not
hold for a post_call block at default settings: post_call needs the complete response before it can
check anything, and on a streaming call the client has already received every chunk by the time that
check even runs. A post_call block on a streamed response does not produce a 400 at all. The client gets a
200, the model’s full output streams through as normal
delta.content chunks, and only after that does a
synthetic data: {"error": {...}} event get appended, which most SSE clients (including the OpenAI SDK)
will surface as an exception, but only after the real content already arrived intact.
GUARDRAIL_INTERVENED (redact) behaves the same way at default settings.
LiteLLM forwards a streamed response to the client chunk-by-chunk as the model generates it,
and by default it does not hold those chunks back behind a post_call guardrail’s verdict.
The first chunk reaches the client in about a second,
well before the check’s roughly twelve-second window can complete,
so a secret or PII value the model streams back
reaches the client before any redaction decision exists to apply.
Streaming protection is available, but it is off by default and covers one route.
Fiddler’s integration does not define LiteLLM’s streaming-aware
async_post_call_streaming_iterator_hook itself.
It does not need to:
because it implements apply_guardrail,
the proxy routes its streamed responses through the shared
UnifiedLLMGuardrails implementation of that hook.
The shared hook’s default mode, block_only, is the unprotected one —
raw chunks stream out as the model produces them,
text rewrites are discarded,
and only an end-of-stream BLOCK terminates the stream,
by which point the content has already been delivered.
Setting streaming_transform_mode: incremental_diff changes that:
delta.content);
Anthropic /v1/messages and the other streaming surfaces
fall back to the unprotected block_only behavior.
And it is ignored when streaming_end_of_stream_only is set.
LiteLLM carries a second, buffer-everything mechanism —
streaming_buffer_until_moderated,
which withholds every chunk until the assembled response has been moderated,
the same shape as the opt-in reject mitigation
AgentGateway’s guardrail page
describes.
It is not reachable from generic_guardrail_api configuration today:
the flag is read from an attribute on the guardrail object,
and the integration neither accepts it as a parameter nor sets it.
Its buffered-replay design also disables itself for content-rewriting guardrails,
so it would cover block and not redaction even if it were exposed.
If you stream on a route incremental_diff does not cover,
either disable streaming for that route
or treat post_call as best-effort there.
Fiddler’s failure_mode
failure_mode controls what happens when an internal check fails to complete —
an inference timeout, an inference server error, or content that exceeds the scan limit.
LiteLLM cannot see these failures because the Fiddler endpoint still returns HTTP 200
with a normal action, so the LiteLLM-side controls never fire.
The default is
open for backward compatibility.
For security-sensitive deployments, set failure_mode: closed, as the quick start does.
With all three controls at their secure values
(fail_closed, fail_on_error: true, failure_mode: closed),
no request bypasses scanning, whether the failure is at the transport, protocol, or detector level.
One caveat: an unexpected exception in the Fiddler pipeline under failure_mode: open
surfaces as an HTTP 5xx rather than a 200,
and is then handled by LiteLLM’s fail_on_error.
A deliberate fail-open posture (failure_mode: open plus fail_on_error: false) trades
protection for availability:
traffic keeps flowing during a guardrail outage, unscanned.
Choose it only for traffic where an unscanned request is acceptable,
and monitor the LiteLLM logs for the fail-open CRITICAL entries.
Timeouts
The guardrail check has one customer-facing timeout: the wall-clock deadline for the whole check pipeline, set per request viatimeout (seconds) in additional_provider_specific_params:
failure_mode governs the outcome:
under open the request proceeds unscanned, under closed it is blocked.
Text Length Limits
The maximum total text length scanned per request is controlled by theGUARDRAILS_MAX_TEXT_LENGTH environment variable on the Fiddler server
(default: 50,000 characters).
Messages are concatenated until the cap is reached;
segments beyond the cap are skipped, never truncated mid-segment:
Tool Call Handling
Whentool_calls contain PII or secrets, Fiddler blocks rather than redacts.
Why: tool-call arguments are structured JSON that the downstream application will parse and execute.
Replacing a value like an email address with [REDACTED EMAIL] would cause send_email
to attempt delivery to a nonsensical address —
producing unpredictable behavior that is worse than blocking outright.
Example — blocked tool call:
Coverage Differs by Client Wire Format
This blocking guarantee holds for requests sent to LiteLLM in OpenAI Chat Completions format (/v1/chat/completions), where message.tool_calls is a native field that LiteLLM
forwards to Fiddler on the pre-call hook.
It does not currently hold for the Anthropic Messages format (/v1/messages), used by
Claude Code and other Anthropic-native clients, and the gap is narrower than “enable
post-call”: LiteLLM’s guardrail-translation layer only extracts an assistant tool_use
block’s arguments into tool_calls on the post-call (response) hook, and only for the
tool call the model is generating in that response. Enabling post-call protects that
one turn, at the moment the model produces the tool call — but a tool_use block already
sitting in conversation history (replayed in every later request, which is how agentic
clients like Claude Code send it) is never re-extracted on the pre-call hook, whether
or not post-call is also enabled. Fiddler’s LLM Gateway runs pre-call only, so neither hook
scans it. The root cause is in LiteLLM itself
(AnthropicMessagesHandler._extract_content_block has no case for tool_use, only for
tool_result), and Fiddler has no visibility into content LiteLLM never forwards, so there
is no Fiddler-side workaround.
Upstream status (as of 2026-09-16). The gap applies to every LiteLLM release up to and
including 1.98.0, the version Fiddler’s LLM Gateway pins.
BerriAI/litellm#40380 was closed by
BerriAI/litellm#40984, which makes the
Anthropic handler extract historical tool_use arguments into tool_calls. That fix is
merged but has not yet appeared in a stable LiteLLM release, and
BerriAI/litellm#41265 reports that it
does not reach guardrails that read only the texts[] input — so do not assume the gap is
closed on the strength of #40984 alone. Re-verify against your own gateway version.
If you depend on this guarantee and your traffic goes through /v1/messages, treat tool
call arguments in conversation history as unscanned.
Tool Results
Fiddler scans tool result content — the contents of a file an agent read, or the output of an MCP tool call — on LiteLLM >= 1.97.0, which is when LiteLLM’s guardrail-translation layer began extracting Anthropictool_result content blocks and OpenAI role: "tool"
messages into the texts[] array it sends to Fiddler. Fiddler’s own scanning is
role-agnostic: every entry in texts[] is scanned identically regardless of which message
role it came from, so no separate configuration is needed once LiteLLM extracts it. Fiddler has
verified this behavior on 1.98.0; 1.97.0 is the version LiteLLM’s own changelog gives for the
extraction, not a boundary Fiddler has tested. Confirm against the version you run.
On an older LiteLLM version, tool result content is not extracted into texts[] at all —
it is visible only inside the structured_messages field, which Fiddler accepts but never
scans (see Request/Response Schema below). If your gateway
predates 1.97.0, tool result content — including file reads and MCP output — is not
scanned, and the fix is to upgrade LiteLLM rather than to change any Fiddler configuration.
Two caveats hold even on a current version:
- Tool results are typed as
anyin the GenAI semantic conventions — they can be plain strings, JSON objects, or arrays. In-place character-span redaction on a serialized JSON payload is not safe if the downstream application re-parses the result as structured data. - This depends on LiteLLM’s own extraction behavior, not a contract Fiddler controls. Test against your specific gateway version before relying on it.
mode: block on secrets and treat tool result content as untrusted.
Troubleshooting
For issues with a specific request, the safe identifiers to include in a support ticket are
litellm_call_id and litellm_trace_id — never include prompts, completions, or credentials.
API Reference
Endpoint
Authorization: Bearer <your-fiddler-api-key>
Request
texts and tool_calls[].function.arguments are scanned by guardrail checks.
The remaining fields are accepted for LiteLLM protocol compatibility,
and unknown fields are ignored.
Response
Fields withnull values are omitted from the wire.
The response shape varies by action:
Guardrail decisions are observable.
With the Fiddler OTel callback enabled on the same proxy,
each guardrail execution is traced as its own span next to the model call,
so every block or redact decision — and its reason — shows up in Explorer as an audit trail.
Next Steps
- Guardrails overview — understand the detection models behind these checks
- LiteLLM Integration — add tracing, token, and cost observability to the same proxy
- LiteLLM Generic Guardrail API spec — the upstream contract this integration implements
- AgentGateway Guardrails — the same Fiddler checks via AgentGateway’s webhook protocol
- Kong AI Gateway Guardrails — Fiddler guardrails via Kong (block-only, no masking)