litellm/litellm
yucheng-berri 5f9dd38867
feat(guardrails): add decision model guardrail with Admin UI flow (#45663)
* feat(guardrails): add decision_model guardrail for decisions-API models

Adds a new guardrail provider that scores request and response text with a
decisions-API model (e.g. Jev) against named predicate checks. Each check
carries its own threshold and action (block or log); a flagged block check
rejects the request with a 400 naming the flagged checks, and call failures
honor unreachable_fallback (fail_open or fail_closed).

Ships four preset checks for the Admin UI (prompt injection, jailbreak,
system prompt extraction, data exfiltration) served from
/guardrails/ui/add_guardrail_settings, plus a Decision Model step in the
add-guardrail form filtered to evaluation-mode models.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(guardrails): fail closed on verdict errors and drop comments in decision_model

* feat(guardrails): cap decision_model input with head and tail elision

* fix(guardrails): list only block checks in decision_model 400s and tighten inputs

* feat(guardrails): honor timeout, cap checks at MAX_DECISION_QUESTIONS, and reject duplicate check names

* fix(guardrails): decorate decision_model apply_guardrail with log_guardrail_information

* fix(guardrails): suppress untyped-decorator pyright error on log_guardrail_information import

* feat(guardrails): screen each text in overlapping chunks with a shared decisions-call semaphore

Replace head/tail elision with per-text screening: each non-empty text is
sent to the decision model on its own, split into overlapping chunks when
it exceeds max_input_chars, and all calls run under a per-event-loop
semaphore shared across requests (max_concurrent_decision_calls,
default 8). Check verdicts aggregate the max probability across calls; a
missing predicate answer on a Block check blocks under fail_closed and
only warns under fail_open, while log-only checks are never flagged for
it. The 400 detail now lists flagged check names only. The provider
combobox also matches Decision Model on jev, typesafe, prompt injection,
jailbreak, and decision

* fix(ui): align decision model custom check rows with preset rows

* fix(ui): move decision model custom check remove button to the row end

* style(ui): run prettier on decision model check files

* fix(ui): inline decision model evaluation-mode filter after lens module removal

* fix(guardrails): keep decision model detections when a chunk call fails

* fix(ui): require an enabled decision model check before create

* fix(guardrails): screen decision model texts sequentially like presidio

* feat(guardrails): replace decision model presets with provider picker and per-question test

* fix(ui): render decision model question test as a full-width row

* feat(ui): add run-history test section to decision model form

* fix(ui): prevent threshold overlap and show test shortcut

* feat(guardrails): default decision model threshold to 0.7

* test(ui): expect decision model default threshold 0.7 in characterization payload

* feat(guardrails): screen tool call arguments with the decision model

* refactor(guardrails): freeze the decision model config model

* feat(guardrails): list only evaluation-mode deployments in the decision model picker

* feat(guardrails): hide the decision model questions table until a question exists

* style(ui): format DecisionModelFields

* style(ui): format decisionModelQuestion tests

* refactor(guardrails): type the tool call function extraction

* refactor(guardrails): build tool call texts without a mutable accumulator

* refactor(ui): share isDecisionMode for the decision model picker

* fix(guardrails): screen prior Responses function call arguments in the decision model guardrail

The Responses input handler leaves function_call arguments out of texts and tool_calls, so a prompt injection in a prior call's arguments passed unscreened. Assistant tool calls from structured messages are now screened too, deduplicated against the request's tool calls

* test(integration): send instructions with the decision model guardrail check

Checks require instructions, so creating the guardrail returned 422 and the test never sent a chat request

* fix(ui): score the decision model test preview the way the guardrail does

An unanswered block question now shows Block, disabled questions no longer count, and a run is hidden once the model or a question's text changes since it was scored

* fix(ui): clear the decision model error on pick and list questions under Add a question

Picking a model after a failed Create left "Select a decision model" on screen, because the form only validates on submit. The field now revalidates when it already shows an error. The Questions table and its heading appear only once a question exists, below the Add a question box

* test(ui): move the decision model form tests into an integration test file

They render the whole AddGuardrailForm, so they belong in a .integration.test.tsx file. Plain fields are now filled with fireEvent.change, and the two existing form test files go back to main apart from the modelHubCall mock the form now needs

* test(guardrails): build the decision model test params without mutating a local

* fix(guardrails): reject list checks outside decision_model and honor streaming scan settings

- LitellmParams now rejects a list `checks` for any guardrail other than
  decision_model, so a Bedrock guardrail with list checks gets 422 again
  instead of being stored and failing every request
- The decision model guardrail reads streaming_end_of_stream_only and
  streaming_sampling_rate, so a streamed post_call response can be scored
  once at end of stream instead of every 5 chunks
- max_concurrent_decision_calls is described as a per-worker limit

* fix(ui): match guardrail providers like the default picker filter

- The provider search uses the Base UI collator filter on the label and
  the aliases, so searches such as presidio_pii or llm_as_a_judge match
  again, as they did before the alias filter
- Model groups from /model_group/info are parsed defensively and after the
  providers are populated, so a malformed response cannot empty the
  provider list

* fix(ui): edit decision model questions in place and show passing test chips in green

Questions start as an Add question button. Each click adds a blank question
card with its name, text, action and threshold, editable until the guardrail
is created, mirroring the per-model budget editor. Create and Next reject a
blank or duplicate enabled question. Test run verdicts and chips use the
success tone for Pass, the error tone for Block and the warning tone for a
flagged Log only question

* fix(ui): drop the per-question enable checkbox from the decision model form

A question is either in the list or removed with its X, so every listed
question is sent and scored. The card now labels Name and Question the way
it labels Action and Threshold

* fix(ui): give the question name field the full card width

* fix(ui): show the provider logo on the selected decision provider

* fix(ui): show the full threshold slider track on decision model questions

* feat(ui): add decision model cards to the guardrail garden

Adds a Decision Model section to the guardrail garden with TypeSafe Jev,
Perplexity, Microsoft, OpenAI and Databricks cards. Each card opens the
create form scoped to that provider's decision models.

The create form drops the Decision Provider picker and lists every
decision model on the proxy with its provider logo, prompts to add a
model when none is available, and says that test runs are billed and
logged.

* fix(ui): shorten the decision model test hint to one line

* fix(ui): prefill the decision model from the garden card's provider

* chore(ui): regenerate the dashboard API types after merging main

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-10 16:00:27 -07:00
..
_v2 feat(cache): select Rust caching through explicit cache objects (#43601) 2026-09-29 00:01:44 +00:00
a2a_protocol refactor(llms): expose public names for private provider helpers (#45037) 2026-10-07 08:49:25 -07:00
anthropic_interface fix(proxy): send a real error event when a /v1/messages stream fails (#41826) 2026-09-25 15:36:35 -07:00
assistants refactor(types): replace Any with proven types in 157 files (#44798) 2026-10-06 15:31:54 +00:00
batch_completion
batches refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
caching fix(caching): give RedisClusterCache one async client per event loop (#45784) 2026-10-10 12:23:45 -07:00
chat_completions refactor(python-bridge): ship a signature base and read the resolved call (#45450) 2026-10-08 17:20:29 -07:00
completion_extras fix(responses): keep a flagged hosted deployment's prompt cache breakpoint on the chat bridge (#45500) 2026-10-09 04:00:39 -07:00
compression refactor(llms): expose public names for private provider helpers (#45037) 2026-10-07 08:49:25 -07:00
containers refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
decisions feat(guardrails): add decision model guardrail with Admin UI flow (#45663) 2026-10-10 16:00:27 -07:00
embeddings refactor(python-bridge): ship a signature base and read the resolved call (#45450) 2026-10-08 17:20:29 -07:00
endpoints/speech/speech_to_completion_bridge
evals
experimental_mcp_client fix(mcp): keep one upstream MCP session per gateway session across tool calls (#42741) 2026-10-10 14:49:45 -07:00
files refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
fine_tuning
google_genai refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
harness refactor(types): replace Any with proven types in 16 files (#45029) 2026-10-07 04:31:51 -07:00
images refactor: expose public hidden_params accessors (#44668) 2026-10-07 00:01:33 -07:00
integrations feat(azure_storage): upload audit logs to Azure Storage via audit_log_callbacks (#43838) 2026-10-10 14:48:56 -07:00
interactions refactor(llms): expose public names for private provider helpers (#45037) 2026-10-07 08:49:25 -07:00
litellm_core_utils feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00
llms fix(sagemaker): keep AWS credentials out of the sagemaker_chat request body (#45724) 2026-10-10 15:30:54 -07:00
messages feat(rust): add the Vertex AI Anthropic Messages config (#45626) 2026-10-09 16:29:45 -07:00
models refactor(skills): move NewSkillRequest to litellm.models.skills (#45768) 2026-10-10 20:33:16 +00:00
ocr refactor(python-bridge): ship a signature base and read the resolved call (#45450) 2026-10-08 17:20:29 -07:00
passthrough refactor(llms): expose public names for private provider helpers (#45037) 2026-10-07 08:49:25 -07:00
proxy feat(guardrails): add decision model guardrail with Admin UI flow (#45663) 2026-10-10 16:00:27 -07:00
proxy_auth
rag perf(types): defer pydantic schema builds via shared LiteLLMBaseModel (#44720) 2026-10-05 22:10:08 -07:00
realtime_api fix(vertex_ai): dial the multi-region Live API host for realtime sessions (#45166) 2026-10-07 17:39:38 -07:00
repositories feat(usage): add top users by spend and user activity views (#45310) 2026-10-10 12:21:43 -07:00
rerank_api feat(lint): add LIT013 flagging *-ok suppressions that suppress nothing and remove the 240 stale ones (#42793) 2026-09-23 17:50:09 -07:00
responses refactor(sdk): import UserAPIKeyAuth from litellm.types.proxy.auth (#45806) 2026-10-10 21:27:48 +00:00
router_strategy refactor(sdk): import UserAPIKeyAuth from litellm.types.proxy.auth (#45806) 2026-10-10 21:27:48 +00:00
router_utils feat(proxy): per-model team member budgets with router fallback (#43887) 2026-10-10 20:33:55 +00:00
rust_bridge docs(agents): ban semicolons and colons in human-facing text (#45684) 2026-10-09 16:36:32 -07:00
sandbox feat: add litellm.agent() to run claude code, codex, opencode and deep agents through the ai gateway (#43885) 2026-10-01 22:27:49 +00:00
search refactor(types): replace Any with proven types in 157 files (#44798) 2026-10-06 15:31:54 +00:00
secret_managers refactor(types): move CommonProxyErrors into litellm/types/proxy (#45745) 2026-10-10 19:06:04 +00:00
skills
systemone feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00
tracing docs(agents): ban semicolons and colons in human-facing text (#45684) 2026-10-09 16:36:32 -07:00
types feat(guardrails): add decision model guardrail with Admin UI flow (#45663) 2026-10-10 16:00:27 -07:00
vector_store_files
vector_stores refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
videos refactor(types): replace Any with proven types in 157 files (#44798) 2026-10-06 15:31:54 +00:00
__init__.py feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00
_internal_context.py fix(otel): nest cache spans under their operation and name service spans by purpose (#44150) 2026-10-03 09:20:27 -07:00
_lazy_imports.py refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
_lazy_imports_registry.py feat(scaledown): add native text provider support (#44168) 2026-10-10 14:01:17 -07:00
_logging.py perf(proxy): keep stream end output and Redis cache debug strings off the event loop (#45252) 2026-10-09 14:56:16 -07:00
_redis.py refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
_redis_credential_provider.py refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
_service_logger.py refactor(sdk): import UserAPIKeyAuth from litellm.types.proxy.auth (#45806) 2026-10-10 21:27:48 +00:00
_uuid.py
_version.py feat(sdk): build core from an independent packaging manifest (#44340) 2026-10-08 18:40:14 -07:00
anthropic_beta_headers_config.json fix(vertex_ai): forward the inline-tools-2026-09-15 beta to Vertex and Anthropic (#45297) 2026-10-08 12:27:52 -07:00
anthropic_beta_headers_manager.py refactor(types): move SpanAttributes, SpecialHeaders and AllowedModelRegion out of proxy._types (#44717) 2026-10-05 21:40:13 -07:00
blog_posts.json
budget_manager.py
constants.py fix(mcp): keep one upstream MCP session per gateway session across tool calls (#42741) 2026-10-10 14:49:45 -07:00
cost.json
cost_calculator.py feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00
exceptions.py fix: support OpenAI SDK 3 while retaining SDK 2 compatibility (#44927) 2026-10-09 19:45:50 -07:00
main.py feat(scaledown): add native text provider support (#44168) 2026-10-10 14:01:17 -07:00
model_prices_and_context_window_backup.json fix(azure): move gpt-realtime-translate deprecation_date to the Models API date (#45849) 2026-10-10 15:00:27 -07:00
policy_templates_backup.json fix(packaging): keep wheel paths under Windows MAX_PATH for Store Python (#43903) 2026-09-30 22:20:36 +00:00
provider_endpoints_support_backup.json feat(scaledown): add native text provider support (#44168) 2026-10-10 14:01:17 -07:00
py.typed
router.py feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00
scheduler.py fix(scheduler): remove a request's queue entry once it stops waiting (#43061) 2026-10-07 17:34:38 -07:00
setup_wizard.py fix(model_prices): correct Claude Sonnet 5.5 capabilities and provider keys (#43587) 2026-09-28 19:12:31 +00:00
timeout.py
tool_loop.py feat(sdk): add run_tool_loop and arun_tool_loop helpers (#44381) 2026-10-03 20:10:30 -07:00
utils.py feat(sdk): add litellm.systemone and trim litellm.decisions to the OpenAI shape (#45846) 2026-10-10 22:16:51 +00:00