Commit graph

641 commits

Author SHA1 Message Date
yassin
0765f6d571 fix(guardrails): keep typesafe registries as dicts so guardrail discovery finds them
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 06:05:43 +00:00
yassin
351afc8519 test(guardrails): cover typesafe failure paths and edge shapes
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 05:10:48 +00:00
yassin
91d4c579e4 refactor(guardrails): freeze or suppress mutable constructions in typesafe guardrail
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 05:06:48 +00:00
yassin
fd4476b130 fix(guardrails): bound typesafe tuning params, preserve result tail, log fail-open status
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 04:49:50 +00:00
yassin
dffb6a38d9 refactor(guardrails): tighten typesafe guardrail typing and error handling
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 04:35:58 +00:00
yassin
4863e1775b feat(guardrails): add TypeSafe Jev relevance-based compaction guardrail
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 04:33:16 +00:00
yucheng-berri
e40b90bbfa
Merge pull request #41220 from BerriAI/litellm_post_call_guardrail_context
fix(guardrails): give post-call scans the scoped request conversation and tools
2026-09-17 00:31:46 -07:00
yucheng
060abd263e fix(guardrails): keep usage chunk and defer tool_calls finish_reason behind held text in incremental_diff
A stream_options.include_usage usage chunk (empty delta plus usage) was folded into the final
transform round and rebuilt without its usage, so token counts and cost vanished from clients.
Metadata-only chunks are now replayed after the final text flush.

A terminal tool-call chunk arriving while earlier text was still held back carried
finish_reason=tool_calls ahead of that text. The finish_reason is now deferred to the final
text chunk whenever the choice has held text.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 05:11:04 +00:00
yucheng
87263cefca Merge remote-tracking branch 'origin/main' into litellm_post_call_guardrail_context
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

# Conflicts:
#	tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py
2026-09-17 05:08:02 +00:00
yucheng
7815719de7 fix(guardrails): stream Prompt Security post_call redactions in incremental_diff mode
Forward streaming_transform_mode from guardrail litellm_params into PromptSecurityGuardrail so incremental_diff is reachable from config; the default stays block_only. In incremental_diff the guardrail now returns stream_holdback_chars alongside the rewritten texts so that a value split across streamed chunks (or across an abbreviation period) is never partially released before the vendor rewrite arrives. Each response text gets its own protect call so modified_text maps back to the right choice when n > 1, and custom_guardrail no longer logs a clean response as mask just because the guardrail attached holdback metadata

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 01:06:12 +00:00
Yassin Kortam
cd08c65002
Merge pull request #41425 from BerriAI/litellm_streaming_buffer_release_on_scan
feat(guardrails): release buffered stream chunks after each passing scan
2026-09-16 14:37:56 -07:00
yassin
8acd2477a6 fix(guardrails): hold legacy function_call stream windows until the end-of-stream scan
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 20:34:20 +00:00
yassin
d5837ab97a test(guardrails): pin tool-call-only scan keys as non-empty
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 19:24:14 +00:00
yassin
ad25fe1886 fix(guardrails): hold unscannable Responses windows and key terminal envelopes by output items
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 18:56:56 +00:00
yassin
0143fe5583 fix(guardrails): hold tool-call windows until the final scan and expose Bedrock streaming flags to the UI
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 18:30:12 +00:00
kerry
07d4936428 fix(anthropic): satisfy strict lint and update tests pinned to the dropped served model
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 17:44:59 +00:00
yassin
64ce436036 Merge remote-tracking branch 'origin/main' into litellm_streaming_buffer_release_on_scan 2026-09-16 17:22:01 +00:00
Yassin Kortam
8aebd4ff63
Merge pull request #40571 from BerriAI/litellm_presidio_mcp_mode_no_post_call_scan
fix(guardrails): don't add post_call output scan for MCP-only Presidio modes
2026-09-16 10:09:12 -07:00
yassin
7b3582aa66 fix(guardrails): treat tag-based Mode as MCP-only when all hooks are MCP hooks
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 16:31:44 +00:00
jesus
47117d880c fix(guardrails): don't add post_call output scan for MCP-only Presidio modes
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 16:15:49 +00:00
Devin AI
4d596082de feat(guardrails): release buffered stream chunks after each passing scan
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 14:20:32 +00:00
yassin
a8fff5b091 fix(content_filter): refuse a trim that splits a conditional word across the cut
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 12:45:58 +00:00
yassin
4fbe631146 test(content_filter): annotate streaming test locals as Final and type the logging metadata
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 12:17:47 +00:00
yassin
60642e875b perf(content_filter): back off refused streamed buffer cuts by one context length
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 11:51:06 +00:00
yassin
7e429dee87 fix(content_filter): keep exception phrases and open conditional sentences in the streamed buffer
Trimming the streamed buffer to the retained tail could drop a category
exception phrase that suppresses a later keyword, or the identifier word
of an unfinished sentence that a conditional category pairs with a later
block word. Refuse the cut while either would leave the buffer so the
bounded scan masks and blocks exactly like a scan of the full text

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 11:18:10 +00:00
yassin
52f06906fe fix(content_filter): widen the streamed scan tail to the longest configured keyword
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 10:58:30 +00:00
yassin
62ecb11ab9 perf(content_filter): scan a bounded window per streamed chunk
The streaming post-call hook rescanned the whole accumulated choice buffer on every chunk, so scan cost grew quadratically with output length. Keep a bounded per-choice buffer instead: once it exceeds twice the scan context, drop the head when masking the head and tail separately yields the same output as masking the whole buffer, so no pattern, phrase or exception straddles the cut. Detections from the dropped head are kept and merged, deduplicated, into the final log row

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 09:59:53 +00:00
Yucheng He
146085669c fix(guardrails): run Singulr logging_only through the base hook, key MCP scans off the proxy call type and type the payloads
Removes the Singulr async_logging_hook and logging_hook overrides so logging_only runs through CustomGuardrail.async_logging_hook: the response scope reaches Singulr as an assistant message instead of a raw ModelResponse dump, a vendor timeout is recorded as guardrail_failed_to_respond, a request-scope block ends the scan, and the sync success callback thread makes no Singulr call.

Decides MCP versus LLM by the proxy logging object's call_type (then the call_type or server-only markers in request_data), never by name, arguments or mcp_tool_name keys a client can put in a chat body. REST /mcp-rest/tools/call pre-scans reach Singulr as mcp_request and a non-mapping arguments value is forwarded as tool_arguments instead of raising.

should_block is a strict bool defaulting to false so a null verdict is an invalid response that block_on_error decides; payload fields drop Any for Sequence, Mapping and AssistantMessage types; metadata carries only the keys present; docstrings and section comments removed per the repo comment policy.
2026-09-15 19:14:49 -07:00
aniket-kardile
8cce2b196a feat(guardrails): singulr v2 API contract with logging_only, pre_mcp_call and post_mcp_call
Squash of BerriAI/litellm#37464 (head da298ca7) by @aniket-kardile, adopted onto main: v2 gateway payload contract with request, response, mcp_request and mcp_response scopes, typed payload models, proxy user, org and team metadata forwarded to Singulr, and the logging_only, pre_mcp_call and post_mcp_call modes.
2026-09-15 19:14:49 -07:00
yucheng-berri
41eb2dbfeb
Merge pull request #41128 from BerriAI/litellm_llm_judge_pre_call
feat(guardrails): support pre_call and during_call modes for llm_as_a_judge
2026-09-15 18:58:21 -07:00
yucheng
f66ffc387e fix(guardrails): only honor the judge call-origin stamp on logging_only in llm_as_a_judge
On pre_call, during_call and post_call the hook data is the client request body, so a
client-supplied litellm_params.metadata.internal_call_origin must not skip enforcement.
Type the during_call helper's request payload as dict[str, object]

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
dd4829398a fix(guardrails): log the configured mode when logging_only is mixed with an enforcing llm_as_a_judge mode
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
10506ab904 fix(guardrails): judge the whole latest user turn, run every during_call guardrail, log combined modes as configured
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
1b8b17cc8a fix(guardrails): judge only the latest request turn in pre_call and during_call llm_as_a_judge
The request-side prompt told the judge to focus on the most recent user turn but the text under review was every extracted request message joined together, so a multi-turn request with an off-topic earlier turn and an on-topic latest turn scored 50 and was blocked. Request-side judging now evaluates the last extracted request text (after the configured message scoping) and passes the full role-labelled conversation only as context. Response-side judging still evaluates all extracted response text

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
e9357d9a6f fix(guardrails): stop logging_only llm_as_a_judge from judging its own judge calls
Judge sub-calls now carry the internal_call_origin metadata stamp and the
guardrail skips any logged call bearing it, so a logging_only judge no longer
recurses into an unbounded chain of judge requests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
a658f20005 test(guardrails): grant premium_user for the tagged Mode case in llm_as_a_judge mode-shape test
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
4d1330ea0b test(guardrails): drop callback-manager patch from llm_as_a_judge mode-shape test
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
28bd00a004 fix(guardrails): label llm_as_a_judge logging_only verdicts with their mode
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
b93f22265c fix(guardrails): give the request-side judge role-labelled conversation context
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:53 +00:00
yucheng
6fccf00d93 fix(guardrails): keep list and tagged mode shapes for llm_as_a_judge
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:52 +00:00
yucheng
0b34800501 fix(guardrails): resolve llm_as_a_judge request-side log mode from event_hook lists, drop unused alias
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:52 +00:00
yucheng
77a6327675 feat(guardrails): support pre_call and during_call modes for llm_as_a_judge
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-16 01:05:52 +00:00
yucheng
9bd3f7b885 Merge remote-tracking branch 'origin/main' into litellm_agent365_mcp_guardrail 2026-09-16 00:52:27 +00:00
yucheng-berri
0b3e56448f
Merge pull request #41126 from BerriAI/litellm_custom_code_guardrail_identity
fix(guardrails): resolve caller identity from metadata buckets in custom code guardrail
2026-09-15 17:47:17 -07:00
Yassin Kortam
d5b96648ea
Merge pull request #41161 from BerriAI/litellm_headroom_protect_cached_prefix
fix(headroom): protect the cached prefix through the last cache_control breakpoint
2026-09-15 12:49:50 -07:00
Yassin Kortam
837423237a
Merge pull request #36775 from MvdB/litellm_presidio_new_entities
feat(guardrails): add new upstream presidio pii entities including german set
2026-09-15 11:26:21 -07:00
yucheng
8e25720c08 fix(guardrails): give post-call scans the scoped request conversation and tools
Response-side guardrail scans on OpenAI Chat Completions, Anthropic Messages, and OpenAI Responses now carry structured_messages (the request turns scoped exactly like the pre-call scan, closed by the model's reply as an assistant turn) and tools (the request's function definitions), in addition to texts, images, and tool_calls.

Guardrails that used structured_messages or tools as a response-side signal (akto, crowdstrike_aidr, hiddenlayer, openai moderations, promptguard, qualifire, straiker) keep their previous response payloads. Logging-only scans whose output translation differs from the input translation get a chat-shaped request so the context survives.

Resolves LIT-6628

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-15 09:58:53 +00:00
Mateo Wang
e5cb8b7534
Merge pull request #40984 from BerriAI/litellm_anthropic_guardrail_system_and_tool_use
fix(guardrails): scan the Anthropic top-level system prompt and tool_use arguments
2026-09-15 00:55:42 -07:00
yucheng-berri
91588221cd
Merge pull request #39050 from BerriAI/litellm_lit6314_guardrail_metadata_transfer
fix(guardrails): record not_run evaluation when scoping leaves nothing to scan
2026-09-14 22:31:16 -07:00
Mateo Wang
a78b24c195
Merge pull request #41172 from BerriAI/litellm_azure_spend_log_zero_cost
fix(proxy): log the provider usage on deferred /v1/messages calls and price cache writes without a creation rate
2026-09-14 22:26:22 -07:00