Skip to content

perf: optimize user_api_key_auth#21140

Merged
ryan-crabbe merged 5 commits intomainfrom
litellm_perf_user_api_key_auth
Feb 22, 2026
Merged

perf: optimize user_api_key_auth#21140
ryan-crabbe merged 5 commits intomainfrom
litellm_perf_user_api_key_auth

Conversation

@ryan-crabbe
Copy link
Collaborator

Relevant issues

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.

Type

🐛 Bug Fix
🧹 Refactoring
✅ Test
Performance

Changes

On a request:

user_api_key_auth was computing the route by calling get_request_route(request) and then right after _user_api_key_auth_builder was callingget_request_route(request) again, throwing time away. The fix for this was getting the route one time and passing it to the auth builder to not have to figure it out again.

get_api_key was looping through pass-through endpoints, even though what was being hit during proxy vs provider benchmark was a /chat/completions request with a bearer token, and then a couple lines later check_api_key_for_custom_headers_or_pass_through_endpoints was being called which made this work redundant.

The fix for this was removing the redundant branch of get_api_key that was doing all that pass through endpoint checking and then leaving check_api_key_for_custom_headers_or_pass_through_endpoints to do that. And then also within check_api_key_for_custom_headers_or_pass_through_endpoints this was optimized to just check that the route starts with one of the pass through prefixes to begin with and that pass_through_endpoints isn't None (the config pass through endpoints that were set).

side note: The old pass through endpoints helper had an isinstance(request.headers, dict) guard before extracting custom headers for configured pass-through endpoints. Starlette's request.headers is a Headers object, not a dict, so this check was always False

Also cached public routes at the module level so its assigned at import time Cached request headers on every request to not have to create a dictionary of them a bunch of times.

Added regression tests as well for these changes.

Overall, this was a 10% improvement in UserAPIKeyAuth, but the most expensive part of this is construction of the AuthUserAPIKey object but I think this is because of line profiler overhead and the object having a lot of None values (tested the speed of constructing this object with a timer outside of the proxy server (with model construct and just init) so not sure.

Before

Screenshot 2026-02-13 at 10 55 46 AM

After

Screenshot 2026-02-13 at 10 56 13 AM

- Fast-path early return in check_api_key_for_custom_headers_or_pass_through_endpoints
- startswith(tuple) replaces for-loop substring matching (also more correct)
- Pre-compute _PUBLIC_ROUTES and MAPPED_PASS_THROUGH_PREFIXES at module level
- Deduplicate get_request_route call by passing route as parameter
- Cache dict(request.headers) on request.state per-request
- Remove redundant elif branch from get_api_key (handled by later function)
- Fix: isinstance(request.headers, dict) was always False for Starlette Headers,
  silently breaking custom header extraction for pass-through endpoints
@vercel
Copy link

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Error Error Feb 22, 2026 0:07am

Request Review

@ryan-crabbe ryan-crabbe changed the title perf: optimize user_api_key_auth hot path perf: optimize user_api_key_auth Feb 13, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 13, 2026

Greptile Summary

Performance optimizations to user_api_key_auth on the critical request path, achieving ~10% improvement by eliminating redundant work: computing the route once instead of twice, caching request headers per-request via request.state, pre-computing public routes and pass-through prefixes at module level, and adding fast-path early returns. Also fixes a latent bug where isinstance(request.headers, dict) was always False (Starlette headers are a Headers object), which silently prevented custom header-based API key extraction for authenticated pass-through endpoints.

  • Eliminates redundant get_request_route() call by passing pre-computed route from user_api_key_auth into _user_api_key_auth_builder
  • Caches dict(request.headers) on request.state._cached_headers to avoid repeated dict construction
  • Pre-computes _PUBLIC_ROUTES and MAPPED_PASS_THROUGH_PREFIXES as module-level constants
  • Removes redundant pass-through endpoint loop from get_api_key (handled by downstream check_api_key_for_custom_headers_or_pass_through_endpoints)
  • Adds fast-path early return in check_api_key_for_custom_headers_or_pass_through_endpoints when route is not a pass-through route
  • Note: route_checks.py changes semantics from substring match (in) to prefix match (startswith) for pass-through route detection — likely correct but worth verifying no routes rely on the old substring behavior
  • Fixes the isinstance(request.headers, dict) guard that was always False, enabling custom header API key extraction for pass-through endpoints with auth enabled

Confidence Score: 4/5

  • This PR is safe to merge — the optimizations are well-targeted and the one behavioral change (substring to prefix match) is practically correct for all known routes.
  • The optimizations are clean, well-tested, and correctly preserve existing behavior in all but one spot: the route_checks.py change from substring (in) to prefix (startswith) matching is a subtle semantic change. While all known pass-through routes use these as prefixes, this should be acknowledged as intentional. The isinstance(request.headers, dict) fix is a genuine bug fix. Header caching is safe since all callers are read-only. Test coverage is good with 7 regression tests.
  • Pay close attention to litellm/proxy/auth/route_checks.py — the in to startswith change alters route matching semantics.

Important Files Changed

Filename Overview
litellm/proxy/auth/user_api_key_auth.py Core performance optimizations: passes pre-computed route to _user_api_key_auth_builder, caches public routes at module level, uses _safe_get_request_headers (cached) instead of dict(request.headers), adds fast-path early return in check_api_key_for_custom_headers_or_pass_through_endpoints, removes redundant pass-through elif from get_api_key, fixes dead-code isinstance(request.headers, dict) guard, and adds break on matching endpoint.
litellm/proxy/_types.py Adds MAPPED_PASS_THROUGH_PREFIXES as a pre-computed tuple constant from LiteLLMRoutes.mapped_pass_through_routes.value for use with str.startswith(). Clean, minimal change.
litellm/proxy/auth/route_checks.py Replaces loop with route.startswith(MAPPED_PASS_THROUGH_PREFIXES) but changes semantics from substring match (in) to prefix match (startswith), which could affect routes where the pass-through prefix appears as a non-prefix substring.
litellm/proxy/common_utils/http_parsing_utils.py Adds per-request caching for _safe_get_request_headers via request.state._cached_headers. All existing callers are read-only, making this safe. Includes proper fallback if request.state is unavailable.
litellm/proxy/pass_through_endpoints/pass_through_endpoints.py Replaces loop with route.startswith(MAPPED_PASS_THROUGH_PREFIXES) — this location already used startswith in its loop, so this is a pure performance optimization with no behavioral change.
tests/test_litellm/proxy/auth/test_user_api_key_auth.py Comprehensive regression tests covering: normal routes, mapped pass-through with header, configured endpoints (auth disabled, langfuse parser, custom headers), removal of get_api_key pass-through elif branch, and header caching. All tests use mocks (no network calls).
tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py Adds State() objects to existing test mocks so that the new header caching in _safe_get_request_headers works correctly — necessary fixup for the caching change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming Request] --> B[user_api_key_auth]
    B --> C["get_request_route() - computed ONCE"]
    C --> D[_user_api_key_auth_builder with pre-computed route]
    D --> E[get_api_key - pass-through elif removed]
    E --> F["_safe_get_request_headers - cached on request.state"]
    F --> G{"route in _PUBLIC_ROUTES?<br/>(module-level set)"}
    G -- Yes --> H[Return public route auth]
    G -- No --> I[check_pass_through_endpoints]
    I --> J{"is_mapped = startswith(PREFIXES)?"}
    J -- "No + no config" --> K[Fast path: return api_key]
    J -- "Yes" --> L[Extract key from header]
    L --> M[Continue auth flow]
    K --> M
    I --> N{"Configured endpoint match?"}
    N -- "auth disabled" --> O[Return UserAPIKeyAuth]
    N -- "langfuse" --> P[Base64 decode key]
    N -- "custom header" --> Q["Extract from headers - isinstance bug fixed"]
    P --> M
    Q --> M
    O --> M
Loading

Last reviewed commit: c7ad805

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 383 to 384
if endpoint.get("auth") is not True:
return UserAPIKeyAuth()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auth: False check may miss falsy values

The condition endpoint.get("auth") is not True will pass for endpoints where auth is explicitly set to False, but it will also pass for endpoints that don't have an auth key at all (returns None), or where auth is any other truthy value like "yes".

Note: this is not a regression - the original code had the same check (endpoint.get("auth") is not True). Just flagging that if someone configures "auth": "enabled" on a pass-through endpoint, it would skip auth entirely since "enabled" is not True evaluates to True.

azure_apim_header: Optional[str],
request_data: dict,
custom_litellm_key_header: Optional[str] = None,
route: Optional[str] = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New route parameter should be typed Optional[str]

The route parameter defaults to None, but the type annotation uses Optional[str] correctly. However, there's no docstring update to explain that callers can now pass in a pre-computed route to avoid redundant get_request_route() calls. A brief inline comment would help future maintainers understand this optimization.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

The _safe_get_request_headers caching uses request.state._cached_headers,
which returns a truthy MagicMock on bare MagicMock() objects instead of
None, breaking content-type detection for form-data tests.
Resolve conflicts:
- pass_through_endpoints.py: take main's version, re-apply
  MAPPED_PASS_THROUGH_PREFIXES startswith(tuple) optimization
- test_user_api_key_auth.py: keep both auth optimization regression
  tests and JWT admin identity field tests
@ryan-crabbe
Copy link
Collaborator Author

@greptileai re review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +350 to +351
if route.startswith(MAPPED_PASS_THROUGH_PREFIXES):
return True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtle behavioral change: startswith vs in

The old code used if _llm_passthrough_route in route (substring match), but the new code uses route.startswith(MAPPED_PASS_THROUGH_PREFIXES) (prefix match). This is a semantic change: the old logic would match routes like /some/path/openai/endpoint where the prefix appears as a substring, while the new logic only matches routes that begin with the prefix.

In practice this is likely the correct behavior (all pass-through routes are defined with these as path prefixes), and the in check was overly broad. However, it should be intentional — if any routes exist where /openai, /anthropic, etc. appear as a non-prefix substring, they would no longer be classified as LLM API routes by _is_llm_api_route.

@ryan-crabbe ryan-crabbe merged commit 0e1db3f into main Feb 22, 2026
70 of 92 checks passed
@ryan-crabbe ryan-crabbe deleted the litellm_perf_user_api_key_auth branch February 22, 2026 00:23
ishaan-jaff added a commit that referenced this pull request Feb 22, 2026
…key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.
krrishdholakia pushed a commit that referenced this pull request Feb 22, 2026
* server root path regression doc

* fixing syntax

* fix: replace Zapier webhook with Google Form for survey submission (#21621)

* Replace Zapier webhook with Google Form for survey submission

* Add back error logging for survey submission debugging

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "Merge pull request #21140 from BerriAI/litellm_perf_user_api_key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.

* test_vertex_ai_gemini_2_5_pro_streaming

* UI new build

* fix rendering

* ui new build

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* release note docs

* docs

* adding image

* fix(vertex_ai): enable context-1m-2025-08-07 beta header

The `context-1m-2025-08-07` Anthropic beta header was set to `null` for vertex_ai,
causing it to be filtered out when users set `extra_headers: {anthropic-beta: context-1m-2025-08-07}`.

This prevented using Claude's 1M context window feature via Vertex AI, resulting in
`prompt is too long: 460500 tokens > 200000 maximum` errors.

Fixes #21861

---------

Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
krrishdholakia added a commit that referenced this pull request Feb 24, 2026
…21970)

* auth_with_role_name add region_name arg for cross-account sts

* update tests to include case with aws_region_name for _auth_with_aws_role

* Only pass region_name to STS client when aws_region_name is set

* Add optional aws_sts_endpoint to _auth_with_aws_role

* Parametrize ambient-credentials test for no opts, region_name, and aws_sts_endpoint

* consistently passing region and endpoint args into explicit credentials irsa

* fix env var leakage

* fix: bedrock openai-compatible imported-model should also have model arn encoded

* feat: show proxy url in ModelHub (#21660)

* fix(bedrock): correct modelInput format for Converse API batch models (#21656)

* fix(proxy): add model_ids param to access group endpoints for precise deployment tagging (#21655)

POST /access_group/new and PUT /access_group/{name}/update now accept an
optional model_ids list that targets specific deployments by their unique
model_id, instead of tagging every deployment that shares a model_name.

When model_ids is provided it takes priority over model_names, giving
API callers the same single-deployment precision that the UI already has
via PATCH /model/{model_id}/update.

Backward compatible: model_names continues to work as before.

Closes #21544

* feat(proxy): add custom favicon support\n\nAdd ability to configure a custom favicon for the litellm proxy UI.\n\n- Add favicon_url field to UIThemeConfig model\n- Add LITELLM_FAVICON_URL env var support\n- Add /get_favicon endpoint to serve custom favicons\n- Update ThemeContext to dynamically set favicon\n- Add favicon URL input to UI theme settings page\n- Add comprehensive tests\n\nCloses #8323 (#21653)

* fix(bedrock): prevent double UUID in create_file S3 key (#21650)

In create_file for Bedrock, get_complete_file_url is called twice:
once in the sync handler (generating UUID-1 for api_base) and once
inside transform_create_file_request (generating UUID-2 for the
actual S3 upload). The Bedrock provider correctly writes UUID-2 into
litellm_params["upload_url"], but the sync handler unconditionally
overwrites it with api_base (UUID-1). This causes the returned
file_id to point to a non-existent S3 key.

Fix: only set upload_url to api_base when transform_create_file_request
has not already set it, preserving the Bedrock provider's value.

Closes #21546

* feat(semantic-cache): support configurable vector dimensions for Qdrant (#21649)

Add vector_size parameter to QdrantSemanticCache and expose it through
the Cache facade as qdrant_semantic_cache_vector_size. This allows users
to use embedding models with dimensions other than the default 1536,
enabling cheaper/stronger models like Stella (1024d), bge-en-icl (4096d),
voyage, cohere, etc.

The parameter defaults to QDRANT_VECTOR_SIZE (env var or 1536) for
backward compatibility. When creating new collections, the configured
vector_size is used instead of the hardcoded constant.

Closes #9377

* fix(utils): normalize camelCase thinking param keys to snake_case (#21762)

Clients like OpenCode's @ai-sdk/openai-compatible send budgetTokens
(camelCase) instead of budget_tokens in the thinking parameter, causing
validation errors. Add early normalization in completion().

* feat: add optional digest mode for Slack alert types (#21683)

Adds per-alert-type digest mode that aggregates duplicate alerts
within a configurable time window and emits a single summary message
with count, start/end timestamps.

Configuration via general_settings.alert_type_config:
  alert_type_config:
    llm_requests_hanging:
      digest: true
      digest_interval: 86400

Digest key: (alert_type, request_model, api_base)
Default interval: 24 hours
Window type: fixed interval

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add blog_posts.json and local backup

* feat: add GetBlogPosts utility with GitHub fetch and local fallback

Adds GetBlogPosts class that fetches blog posts from GitHub with a 1-hour
in-process TTL cache, validates the response, and falls back to the bundled
blog_posts_backup.json on any network or validation failure.

* test: add cache reset fixture and LITELLM_LOCAL_BLOG_POSTS test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GET /public/litellm_blog_posts endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: log fallback warning in blog posts endpoint and tighten test

* feat: add disable_show_blog to UISettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add useUISettings and useDisableShowBlog hooks

* fix: rename useUISettings to useUISettingsFlags to avoid naming collision

* fix: use existing useUISettings hook in useDisableShowBlog to avoid cache duplication

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown component with react-query and error/retry state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: enforce 5-post limit in BlogDropdown and add cap test

* fix: add retry, stable post key, enabled guard in BlogDropdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown to navbar after Docs link

* feat: add network_mock transport for benchmarking proxy overhead without real API calls

Intercepts at httpx transport layer so the full proxy path (auth, routing,
OpenAI SDK, response transformation) is exercised with zero-latency responses.
Activated via `litellm_settings: { network_mock: true }` in proxy config.

* Litellm dev 02 19 2026 p2 (#21871)

* feat(ui/): new guardrails monitor 'demo

mock representation of what guardrails monitor looks like

* fix: ui updates

* style(ui/): fix styling

* feat: enable running ai monitor on individual guardrails

* feat: add backend logic for guardrail monitoring

* fix(guardrails/usage_endpoints.py): fix usage dashboard

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo (#21754)

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo

* fix(budget): update stale docstring on get_budget_reset_time

* fix: add missing return type annotations to iterator protocol methods in streaming_handler (#21750)

* fix: add return type annotations to iterator protocol methods in streaming_handler

Add missing return type annotations to __iter__, __aiter__, __next__, and __anext__ methods in CustomStreamWrapper and related classes.

- __iter__(self) -> Iterator["ModelResponseStream"]
- __aiter__(self) -> AsyncIterator["ModelResponseStream"]
- __next__(self) -> "ModelResponseStream"
- __anext__(self) -> "ModelResponseStream"

Also adds AsyncIterator and Iterator to typing imports.

Fixes issue with PLR0915 noqa comments and ensures proper type checking support.
Related to: #8304

* fix: add ruff PLR0915 noqa for files with too many statements

* Add gollem Go agent framework cookbook example (#21747)

Show how to use gollem, a production Go agent framework, with
LiteLLM proxy for multi-provider LLM access including tool use
and streaming.

* fix: avoid mutating caller-owned dicts in SpendUpdateQueue aggregation (#21742)

* fix(vertex_ai): enable context-1m-2025-08-07 beta header (#21870)

* server root path regression doc

* fixing syntax

* fix: replace Zapier webhook with Google Form for survey submission (#21621)

* Replace Zapier webhook with Google Form for survey submission

* Add back error logging for survey submission debugging

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "Merge pull request #21140 from BerriAI/litellm_perf_user_api_key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.

* test_vertex_ai_gemini_2_5_pro_streaming

* UI new build

* fix rendering

* ui new build

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* release note docs

* docs

* adding image

* fix(vertex_ai): enable context-1m-2025-08-07 beta header

The `context-1m-2025-08-07` Anthropic beta header was set to `null` for vertex_ai,
causing it to be filtered out when users set `extra_headers: {anthropic-beta: context-1m-2025-08-07}`.

This prevented using Claude's 1M context window feature via Vertex AI, resulting in
`prompt is too long: 460500 tokens > 200000 maximum` errors.

Fixes #21861

---------

Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "fix(vertex_ai): enable context-1m-2025-08-07 beta header (#21870)" (#21876)

This reverts commit bce078a.

* docs(ui): add pre-PR checklist to UI contributing guide

Add testing and build verification steps per maintainer feedback
from @yjiang-litellm. Contributors should run their related tests
per-file and ensure npm run build passes before opening PRs.

* Fix entries with fast and us/

* Add tests for fast and us

* Add support for Priority PayGo for vertex ai and gemini

* Add model pricing

* fix: ensure arrival_time is set before calculating queue time

* Fix: Anthropic model wildcard access issue

* Add incident report

* Add ability to see which model cost map is getting used

* Fix name of title

* Readd tpm limit

* State management fixes for CheckBatchCost

* Fix PR review comments

* State management fixes for CheckBatchCost - Address greptile comments

* fix mypy issues:

* Add Noma guardrails v2 based on custom guardrails (#21400)

* Fix code qa issues

* Fix mypy issues

* Fix mypy issues

* Fix test_aaamodel_prices_and_context_window_json_is_valid

* fix: update calendly on repo

* fix(tests): use counter-based mock for time.time in prisma self-heal test

The test used a fixed side_effect list for time.time(), but the number
of calls varies by Python version, causing StopIteration on 3.12 and
AssertionError on 3.14. Replace with an infinite counter-based callable
and assert the timestamp was updated rather than checking for an exact
value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tests): use absolute path for model_prices JSON in validation test

The test used a relative path 'litellm/model_prices_and_context_window.json'
which only works when pytest runs from a specific working directory.
Use os.path based on __file__ to resolve the path reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update tests/test_litellm/test_utils.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(tests): use os.path instead of Path to avoid NameError

Path is not imported at module level. Use os.path.join which is already
available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* clean up mock transport: remove streaming, add defensive parsing

* docs: add Google GenAI SDK tutorial (JS & Python) (#21885)

* docs: add Google GenAI SDK tutorial for JS and Python

Add tutorial for using Google's official GenAI SDK (@google/genai for JS,
google-genai for Python) with LiteLLM proxy. Covers pass-through and
native router endpoints, streaming, multi-turn chat, and multi-provider
routing via model_group_alias. Also updates pass-through docs to use the
new SDK replacing the deprecated @google/generative-ai.

* fix(docs): correct Python SDK env var name in GenAI tutorial

GOOGLE_GENAI_API_KEY does not exist in the google-genai SDK.
The correct env var is GEMINI_API_KEY (or GOOGLE_API_KEY).
Also note that the Python SDK has no base URL env var.

* fix(docs): replace non-existent GOOGLE_GENAI_BASE_URL env var in interactions.md

The Python google-genai SDK does not read GOOGLE_GENAI_BASE_URL.
Use http_options={"base_url": "..."} in code instead.

* docs: add network mock benchmarking section

* docs: tweak benchmarks wording

* fix: add auth headers and empty latencies guard to benchmark script

* refactor: use method-level import for MockOpenAITransport

* fix: guard print_aggregate against empty latencies

* fix: add INCOMPLETE status to Interactions API enum and test

Google added INCOMPLETE to the Interactions API OpenAPI spec status enum.
Update both the Status3 enum in the SDK types and the test's expected
values to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Guardrail Monitor - measure guardrail reliability in prod  (#21944)

* fix: fix log viewer for guardrail monitoring

* feat(ui/): fix rendering logs per guardrail

* fix: fix viewing logs on overview tab of guardrail

* fix: log viewer

* fix: fix naming to align with metric

* docs: add performance & reliability section to v1.81.14 release notes

* fix(tests): make RPM limit test sequential to avoid race condition

Concurrent requests via run_in_executor + asyncio.gather caused a race
condition where more requests slipped through the rate limiter than
expected, leading to flaky test failures (e.g. 3 successes instead of 2
with rpm_limit=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: Singapore guardrail policies (PDPA + MAS AI Risk Management) (#21948)

* feat: Singapore PDPA PII protection guardrail policy template

Add Singapore Personal Data Protection Act (PDPA) guardrail support:

Regex patterns (patterns.json):
- sg_nric: NRIC/FIN detection ([STFGM] + 7 digits + checksum letter)
- sg_phone: Singapore phone numbers (+65/0065/65 prefix)
- sg_postal_code: 6-digit postal codes (contextual)
- passport_singapore: Passport numbers (E/K + 7 digits, contextual)
- sg_uen: Unique Entity Numbers (3 formats)
- sg_bank_account: Bank account numbers (dash format, contextual)

YAML policy templates (5 sub-guardrails):
- sg_pdpa_personal_identifiers: s.13 Consent
- sg_pdpa_sensitive_data: Advisory Guidelines
- sg_pdpa_do_not_call: Part IX DNC Registry
- sg_pdpa_data_transfer: s.26 overseas transfers
- sg_pdpa_profiling_automated_decisions: Model AI Governance Framework

Policy template entry in policy_templates.json with 9 guardrail definitions
(4 regex-based + 5 YAML conditional keyword matching).

Tests:
- test_sg_patterns.py: regex pattern unit tests
- test_sg_pdpa_guardrails.py: conditional keyword matching tests (100+ cases)

* feat: MAS AI Risk Management Guidelines guardrail policy template

Add Monetary Authority of Singapore (MAS) AI Risk Management Guidelines
guardrail support for financial institutions:

YAML policy templates (5 sub-guardrails):
- sg_mas_fairness_bias: Blocks discriminatory financial AI (credit/loans/insurance by protected attributes)
- sg_mas_transparency_explainability: Blocks opaque/unexplainable AI for consequential financial decisions
- sg_mas_human_oversight: Blocks fully automated financial decisions without human-in-the-loop
- sg_mas_data_governance: Blocks unauthorized sharing/mishandling of financial customer data
- sg_mas_model_security: Blocks adversarial attacks, model poisoning, inversion on financial AI

Policy template entry in policy_templates.json with 5 guardrail definitions.
Aligned with MAS FEAT Principles, Project MindForge, and NIST AI RMF.

Tests:
- test_sg_mas_ai_guardrails.py: conditional keyword matching tests (100+ cases)

* fix: address SG pattern review feedback

- Update NRIC lowercase test for IGNORECASE runtime behavior
- Add keyword context guard to sg_uen pattern to reduce false positives

* docs: clarify MAS AIRM timeline references

- Explicitly mark MAS AIRM as Nov 2025 consultation draft
- Add 2018 qualifier for FEAT principles in MAS policy descriptions
- Update MAS guardrail wording to avoid release-year ambiguity

* chore: commit resolved MAS policy conflicts

* test:

* chore:

* Add OpenAI Agents SDK tutorial with LiteLLM Proxy to docs  (#21221)

* Add OpenAI Agents SDK tutorial to docs

* Update OpenAI Agents SDK tutorial to use LiteLLM environment variables

* Enhance OpenAI Agents SDK tutorial with built-in LiteLLM extension details and updated configuration steps. Adjust section headings for clarity and improve the flow of information regarding model setup and usage.

* adjust blog posts to fetch from github first

* feat(videos): add variant parameter to video content download (#21955)

openai videos models support the features to download variants.
See more details here: https://developers.openai.com/api/docs/guides/video-generation#use-image-references.
Plumb variant (e.g. "thumbnail", "spritesheet") through the full
video content download chain: avideo_content → video_content →
video_content_handler → transform_video_content_request. OpenAI
appends ?variant=<value> to the GET URL; other providers accept
the parameter in their signature but ignore it.

* fixing path

* adjust blog post path

* Revert duplicate issue checker to text-based matching, remove duplicate PR workflow

Remove the Claude Code-powered duplicate PR detection workflow and revert
the duplicate issue checker back to wow-actions/potential-duplicates with
text similarity matching.

* ui changes

* adding tests

* adjust default aggregation threshold

* fix(videos): pass api_key from litellm_params to video remix handlers (#21965)

video_remix_handler and async_video_remix_handler were not falling back
to litellm_params.api_key when the api_key parameter was None, causing
Authorization: Bearer None to be sent to the provider. This matches the
pattern already used by async_video_generation_handler.

* adding testing coverage + fixing flaky tests

* fix(ollama): thread api_base through get_model_info and add graceful fallback

When users pass api_base to litellm.completion() for Ollama, the model
info fetch (context window, function_calling support) was ignoring the
user's api_base and only reading OLLAMA_API_BASE env var or defaulting
to localhost:11434. This caused confusing errors in logs when Ollama
runs on a remote server.

Thread api_base from litellm_params through the get_model_info call
chain so OllamaConfig.get_model_info() uses the correct server. Also
return safe defaults instead of raising when the server is unreachable.

Fixes #21967

---------

Co-authored-by: An Tang <ta@stripe.com>
Co-authored-by: janfrederickk <75388864+janfrederickk@users.noreply.github.com>
Co-authored-by: Zhenting Huang <3061613175@qq.com>
Co-authored-by: Darien Kindlund <darien@kindlund.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: Ryan Crabbe <rcrabbe@berkeley.edu>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: LeeJuOh <56071126+LeeJuOh@users.noreply.github.com>
Co-authored-by: Monesh Ram <31161039+WhoisMonesh@users.noreply.github.com>
Co-authored-by: Trevor Prater <trevor.prater@gmail.com>
Co-authored-by: The Mavik <179817126+themavik@users.noreply.github.com>
Co-authored-by: Edwin Isac <33712823+edwiniac@users.noreply.github.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Harshit Jain <harshitjain0562@gmail.com>
Co-authored-by: Harshit Jain <48647625+Harshit28j@users.noreply.github.com>
Co-authored-by: Ephrim Stanley <ephrim.stanley@point72.com>
Co-authored-by: TomAlon <tom@noma.security>
Co-authored-by: Julio Quinteros Pro <jquinter@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Ron Zhong <ron-zhong@hotmail.com>
Co-authored-by: Arindam Majumder <109217591+Arindam200@users.noreply.github.com>
Co-authored-by: Lei Nie <lenie@quora.com>
krrishdholakia added a commit that referenced this pull request Feb 24, 2026
…voke (#21964)

* auth_with_role_name add region_name arg for cross-account sts

* update tests to include case with aws_region_name for _auth_with_aws_role

* Only pass region_name to STS client when aws_region_name is set

* Add optional aws_sts_endpoint to _auth_with_aws_role

* Parametrize ambient-credentials test for no opts, region_name, and aws_sts_endpoint

* consistently passing region and endpoint args into explicit credentials irsa

* fix env var leakage

* fix: bedrock openai-compatible imported-model should also have model arn encoded

* feat: show proxy url in ModelHub (#21660)

* fix(bedrock): correct modelInput format for Converse API batch models (#21656)

* fix(proxy): add model_ids param to access group endpoints for precise deployment tagging (#21655)

POST /access_group/new and PUT /access_group/{name}/update now accept an
optional model_ids list that targets specific deployments by their unique
model_id, instead of tagging every deployment that shares a model_name.

When model_ids is provided it takes priority over model_names, giving
API callers the same single-deployment precision that the UI already has
via PATCH /model/{model_id}/update.

Backward compatible: model_names continues to work as before.

Closes #21544

* feat(proxy): add custom favicon support\n\nAdd ability to configure a custom favicon for the litellm proxy UI.\n\n- Add favicon_url field to UIThemeConfig model\n- Add LITELLM_FAVICON_URL env var support\n- Add /get_favicon endpoint to serve custom favicons\n- Update ThemeContext to dynamically set favicon\n- Add favicon URL input to UI theme settings page\n- Add comprehensive tests\n\nCloses #8323 (#21653)

* fix(bedrock): prevent double UUID in create_file S3 key (#21650)

In create_file for Bedrock, get_complete_file_url is called twice:
once in the sync handler (generating UUID-1 for api_base) and once
inside transform_create_file_request (generating UUID-2 for the
actual S3 upload). The Bedrock provider correctly writes UUID-2 into
litellm_params["upload_url"], but the sync handler unconditionally
overwrites it with api_base (UUID-1). This causes the returned
file_id to point to a non-existent S3 key.

Fix: only set upload_url to api_base when transform_create_file_request
has not already set it, preserving the Bedrock provider's value.

Closes #21546

* feat(semantic-cache): support configurable vector dimensions for Qdrant (#21649)

Add vector_size parameter to QdrantSemanticCache and expose it through
the Cache facade as qdrant_semantic_cache_vector_size. This allows users
to use embedding models with dimensions other than the default 1536,
enabling cheaper/stronger models like Stella (1024d), bge-en-icl (4096d),
voyage, cohere, etc.

The parameter defaults to QDRANT_VECTOR_SIZE (env var or 1536) for
backward compatibility. When creating new collections, the configured
vector_size is used instead of the hardcoded constant.

Closes #9377

* fix(utils): normalize camelCase thinking param keys to snake_case (#21762)

Clients like OpenCode's @ai-sdk/openai-compatible send budgetTokens
(camelCase) instead of budget_tokens in the thinking parameter, causing
validation errors. Add early normalization in completion().

* feat: add optional digest mode for Slack alert types (#21683)

Adds per-alert-type digest mode that aggregates duplicate alerts
within a configurable time window and emits a single summary message
with count, start/end timestamps.

Configuration via general_settings.alert_type_config:
  alert_type_config:
    llm_requests_hanging:
      digest: true
      digest_interval: 86400

Digest key: (alert_type, request_model, api_base)
Default interval: 24 hours
Window type: fixed interval

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add blog_posts.json and local backup

* feat: add GetBlogPosts utility with GitHub fetch and local fallback

Adds GetBlogPosts class that fetches blog posts from GitHub with a 1-hour
in-process TTL cache, validates the response, and falls back to the bundled
blog_posts_backup.json on any network or validation failure.

* test: add cache reset fixture and LITELLM_LOCAL_BLOG_POSTS test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GET /public/litellm_blog_posts endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: log fallback warning in blog posts endpoint and tighten test

* feat: add disable_show_blog to UISettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add useUISettings and useDisableShowBlog hooks

* fix: rename useUISettings to useUISettingsFlags to avoid naming collision

* fix: use existing useUISettings hook in useDisableShowBlog to avoid cache duplication

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown component with react-query and error/retry state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: enforce 5-post limit in BlogDropdown and add cap test

* fix: add retry, stable post key, enabled guard in BlogDropdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown to navbar after Docs link

* feat: add network_mock transport for benchmarking proxy overhead without real API calls

Intercepts at httpx transport layer so the full proxy path (auth, routing,
OpenAI SDK, response transformation) is exercised with zero-latency responses.
Activated via `litellm_settings: { network_mock: true }` in proxy config.

* Litellm dev 02 19 2026 p2 (#21871)

* feat(ui/): new guardrails monitor 'demo

mock representation of what guardrails monitor looks like

* fix: ui updates

* style(ui/): fix styling

* feat: enable running ai monitor on individual guardrails

* feat: add backend logic for guardrail monitoring

* fix(guardrails/usage_endpoints.py): fix usage dashboard

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo (#21754)

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo

* fix(budget): update stale docstring on get_budget_reset_time

* fix: add missing return type annotations to iterator protocol methods in streaming_handler (#21750)

* fix: add return type annotations to iterator protocol methods in streaming_handler

Add missing return type annotations to __iter__, __aiter__, __next__, and __anext__ methods in CustomStreamWrapper and related classes.

- __iter__(self) -> Iterator["ModelResponseStream"]
- __aiter__(self) -> AsyncIterator["ModelResponseStream"]
- __next__(self) -> "ModelResponseStream"
- __anext__(self) -> "ModelResponseStream"

Also adds AsyncIterator and Iterator to typing imports.

Fixes issue with PLR0915 noqa comments and ensures proper type checking support.
Related to: #8304

* fix: add ruff PLR0915 noqa for files with too many statements

* Add gollem Go agent framework cookbook example (#21747)

Show how to use gollem, a production Go agent framework, with
LiteLLM proxy for multi-provider LLM access including tool use
and streaming.

* fix: avoid mutating caller-owned dicts in SpendUpdateQueue aggregation (#21742)

* fix(vertex_ai): enable context-1m-2025-08-07 beta header (#21870)

* server root path regression doc

* fixing syntax

* fix: replace Zapier webhook with Google Form for survey submission (#21621)

* Replace Zapier webhook with Google Form for survey submission

* Add back error logging for survey submission debugging

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "Merge pull request #21140 from BerriAI/litellm_perf_user_api_key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.

* test_vertex_ai_gemini_2_5_pro_streaming

* UI new build

* fix rendering

* ui new build

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* release note docs

* docs

* adding image

* fix(vertex_ai): enable context-1m-2025-08-07 beta header

The `context-1m-2025-08-07` Anthropic beta header was set to `null` for vertex_ai,
causing it to be filtered out when users set `extra_headers: {anthropic-beta: context-1m-2025-08-07}`.

This prevented using Claude's 1M context window feature via Vertex AI, resulting in
`prompt is too long: 460500 tokens > 200000 maximum` errors.

Fixes #21861

---------

Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "fix(vertex_ai): enable context-1m-2025-08-07 beta header (#21870)" (#21876)

This reverts commit bce078a.

* docs(ui): add pre-PR checklist to UI contributing guide

Add testing and build verification steps per maintainer feedback
from @yjiang-litellm. Contributors should run their related tests
per-file and ensure npm run build passes before opening PRs.

* Fix entries with fast and us/

* Add tests for fast and us

* Add support for Priority PayGo for vertex ai and gemini

* Add model pricing

* fix: ensure arrival_time is set before calculating queue time

* Fix: Anthropic model wildcard access issue

* Add incident report

* Add ability to see which model cost map is getting used

* Fix name of title

* Readd tpm limit

* State management fixes for CheckBatchCost

* Fix PR review comments

* State management fixes for CheckBatchCost - Address greptile comments

* fix mypy issues:

* Add Noma guardrails v2 based on custom guardrails (#21400)

* Fix code qa issues

* Fix mypy issues

* Fix mypy issues

* Fix test_aaamodel_prices_and_context_window_json_is_valid

* fix: update calendly on repo

* fix(tests): use counter-based mock for time.time in prisma self-heal test

The test used a fixed side_effect list for time.time(), but the number
of calls varies by Python version, causing StopIteration on 3.12 and
AssertionError on 3.14. Replace with an infinite counter-based callable
and assert the timestamp was updated rather than checking for an exact
value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tests): use absolute path for model_prices JSON in validation test

The test used a relative path 'litellm/model_prices_and_context_window.json'
which only works when pytest runs from a specific working directory.
Use os.path based on __file__ to resolve the path reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update tests/test_litellm/test_utils.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(tests): use os.path instead of Path to avoid NameError

Path is not imported at module level. Use os.path.join which is already
available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* clean up mock transport: remove streaming, add defensive parsing

* docs: add Google GenAI SDK tutorial (JS & Python) (#21885)

* docs: add Google GenAI SDK tutorial for JS and Python

Add tutorial for using Google's official GenAI SDK (@google/genai for JS,
google-genai for Python) with LiteLLM proxy. Covers pass-through and
native router endpoints, streaming, multi-turn chat, and multi-provider
routing via model_group_alias. Also updates pass-through docs to use the
new SDK replacing the deprecated @google/generative-ai.

* fix(docs): correct Python SDK env var name in GenAI tutorial

GOOGLE_GENAI_API_KEY does not exist in the google-genai SDK.
The correct env var is GEMINI_API_KEY (or GOOGLE_API_KEY).
Also note that the Python SDK has no base URL env var.

* fix(docs): replace non-existent GOOGLE_GENAI_BASE_URL env var in interactions.md

The Python google-genai SDK does not read GOOGLE_GENAI_BASE_URL.
Use http_options={"base_url": "..."} in code instead.

* docs: add network mock benchmarking section

* docs: tweak benchmarks wording

* fix: add auth headers and empty latencies guard to benchmark script

* refactor: use method-level import for MockOpenAITransport

* fix: guard print_aggregate against empty latencies

* fix: add INCOMPLETE status to Interactions API enum and test

Google added INCOMPLETE to the Interactions API OpenAPI spec status enum.
Update both the Status3 enum in the SDK types and the test's expected
values to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Guardrail Monitor - measure guardrail reliability in prod  (#21944)

* fix: fix log viewer for guardrail monitoring

* feat(ui/): fix rendering logs per guardrail

* fix: fix viewing logs on overview tab of guardrail

* fix: log viewer

* fix: fix naming to align with metric

* docs: add performance & reliability section to v1.81.14 release notes

* fix(tests): make RPM limit test sequential to avoid race condition

Concurrent requests via run_in_executor + asyncio.gather caused a race
condition where more requests slipped through the rate limiter than
expected, leading to flaky test failures (e.g. 3 successes instead of 2
with rpm_limit=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: Singapore guardrail policies (PDPA + MAS AI Risk Management) (#21948)

* feat: Singapore PDPA PII protection guardrail policy template

Add Singapore Personal Data Protection Act (PDPA) guardrail support:

Regex patterns (patterns.json):
- sg_nric: NRIC/FIN detection ([STFGM] + 7 digits + checksum letter)
- sg_phone: Singapore phone numbers (+65/0065/65 prefix)
- sg_postal_code: 6-digit postal codes (contextual)
- passport_singapore: Passport numbers (E/K + 7 digits, contextual)
- sg_uen: Unique Entity Numbers (3 formats)
- sg_bank_account: Bank account numbers (dash format, contextual)

YAML policy templates (5 sub-guardrails):
- sg_pdpa_personal_identifiers: s.13 Consent
- sg_pdpa_sensitive_data: Advisory Guidelines
- sg_pdpa_do_not_call: Part IX DNC Registry
- sg_pdpa_data_transfer: s.26 overseas transfers
- sg_pdpa_profiling_automated_decisions: Model AI Governance Framework

Policy template entry in policy_templates.json with 9 guardrail definitions
(4 regex-based + 5 YAML conditional keyword matching).

Tests:
- test_sg_patterns.py: regex pattern unit tests
- test_sg_pdpa_guardrails.py: conditional keyword matching tests (100+ cases)

* feat: MAS AI Risk Management Guidelines guardrail policy template

Add Monetary Authority of Singapore (MAS) AI Risk Management Guidelines
guardrail support for financial institutions:

YAML policy templates (5 sub-guardrails):
- sg_mas_fairness_bias: Blocks discriminatory financial AI (credit/loans/insurance by protected attributes)
- sg_mas_transparency_explainability: Blocks opaque/unexplainable AI for consequential financial decisions
- sg_mas_human_oversight: Blocks fully automated financial decisions without human-in-the-loop
- sg_mas_data_governance: Blocks unauthorized sharing/mishandling of financial customer data
- sg_mas_model_security: Blocks adversarial attacks, model poisoning, inversion on financial AI

Policy template entry in policy_templates.json with 5 guardrail definitions.
Aligned with MAS FEAT Principles, Project MindForge, and NIST AI RMF.

Tests:
- test_sg_mas_ai_guardrails.py: conditional keyword matching tests (100+ cases)

* fix: address SG pattern review feedback

- Update NRIC lowercase test for IGNORECASE runtime behavior
- Add keyword context guard to sg_uen pattern to reduce false positives

* docs: clarify MAS AIRM timeline references

- Explicitly mark MAS AIRM as Nov 2025 consultation draft
- Add 2018 qualifier for FEAT principles in MAS policy descriptions
- Update MAS guardrail wording to avoid release-year ambiguity

* chore: commit resolved MAS policy conflicts

* test:

* chore:

* Add OpenAI Agents SDK tutorial with LiteLLM Proxy to docs  (#21221)

* Add OpenAI Agents SDK tutorial to docs

* Update OpenAI Agents SDK tutorial to use LiteLLM environment variables

* Enhance OpenAI Agents SDK tutorial with built-in LiteLLM extension details and updated configuration steps. Adjust section headings for clarity and improve the flow of information regarding model setup and usage.

* adjust blog posts to fetch from github first

* feat(videos): add variant parameter to video content download (#21955)

openai videos models support the features to download variants.
See more details here: https://developers.openai.com/api/docs/guides/video-generation#use-image-references.
Plumb variant (e.g. "thumbnail", "spritesheet") through the full
video content download chain: avideo_content → video_content →
video_content_handler → transform_video_content_request. OpenAI
appends ?variant=<value> to the GET URL; other providers accept
the parameter in their signature but ignore it.

* fixing path

* adjust blog post path

* Revert duplicate issue checker to text-based matching, remove duplicate PR workflow

Remove the Claude Code-powered duplicate PR detection workflow and revert
the duplicate issue checker back to wow-actions/potential-duplicates with
text similarity matching.

* ui changes

* adding tests

* fix(anthropic): sanitize tool_use IDs in assistant messages

Apply _sanitize_anthropic_tool_use_id to tool_use blocks in
convert_to_anthropic_tool_invoke, not just tool_result blocks.
IDs from external frameworks (e.g. MiniMax) may contain characters
like colons that violate Anthropic's ^[a-zA-Z0-9_-]+$ pattern.

Adds test for invalid ID sanitization in tool_use blocks.

---------

Co-authored-by: An Tang <ta@stripe.com>
Co-authored-by: janfrederickk <75388864+janfrederickk@users.noreply.github.com>
Co-authored-by: Zhenting Huang <3061613175@qq.com>
Co-authored-by: Cesar Garcia <128240629+Chesars@users.noreply.github.com>
Co-authored-by: Darien Kindlund <darien@kindlund.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: Ryan Crabbe <rcrabbe@berkeley.edu>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: LeeJuOh <56071126+LeeJuOh@users.noreply.github.com>
Co-authored-by: Monesh Ram <31161039+WhoisMonesh@users.noreply.github.com>
Co-authored-by: Trevor Prater <trevor.prater@gmail.com>
Co-authored-by: The Mavik <179817126+themavik@users.noreply.github.com>
Co-authored-by: Edwin Isac <33712823+edwiniac@users.noreply.github.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Chesars <cesarponce19544@gmail.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Harshit Jain <harshitjain0562@gmail.com>
Co-authored-by: Harshit Jain <48647625+Harshit28j@users.noreply.github.com>
Co-authored-by: Ephrim Stanley <ephrim.stanley@point72.com>
Co-authored-by: TomAlon <tom@noma.security>
Co-authored-by: Julio Quinteros Pro <jquinter@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Ron Zhong <ron-zhong@hotmail.com>
Co-authored-by: Arindam Majumder <109217591+Arindam200@users.noreply.github.com>
Co-authored-by: Lei Nie <lenie@quora.com>
damhau pushed a commit to damhau/litellm that referenced this pull request Feb 26, 2026
…erriAI#21970)

* auth_with_role_name add region_name arg for cross-account sts

* update tests to include case with aws_region_name for _auth_with_aws_role

* Only pass region_name to STS client when aws_region_name is set

* Add optional aws_sts_endpoint to _auth_with_aws_role

* Parametrize ambient-credentials test for no opts, region_name, and aws_sts_endpoint

* consistently passing region and endpoint args into explicit credentials irsa

* fix env var leakage

* fix: bedrock openai-compatible imported-model should also have model arn encoded

* feat: show proxy url in ModelHub (BerriAI#21660)

* fix(bedrock): correct modelInput format for Converse API batch models (BerriAI#21656)

* fix(proxy): add model_ids param to access group endpoints for precise deployment tagging (BerriAI#21655)

POST /access_group/new and PUT /access_group/{name}/update now accept an
optional model_ids list that targets specific deployments by their unique
model_id, instead of tagging every deployment that shares a model_name.

When model_ids is provided it takes priority over model_names, giving
API callers the same single-deployment precision that the UI already has
via PATCH /model/{model_id}/update.

Backward compatible: model_names continues to work as before.

Closes BerriAI#21544

* feat(proxy): add custom favicon support\n\nAdd ability to configure a custom favicon for the litellm proxy UI.\n\n- Add favicon_url field to UIThemeConfig model\n- Add LITELLM_FAVICON_URL env var support\n- Add /get_favicon endpoint to serve custom favicons\n- Update ThemeContext to dynamically set favicon\n- Add favicon URL input to UI theme settings page\n- Add comprehensive tests\n\nCloses BerriAI#8323 (BerriAI#21653)

* fix(bedrock): prevent double UUID in create_file S3 key (BerriAI#21650)

In create_file for Bedrock, get_complete_file_url is called twice:
once in the sync handler (generating UUID-1 for api_base) and once
inside transform_create_file_request (generating UUID-2 for the
actual S3 upload). The Bedrock provider correctly writes UUID-2 into
litellm_params["upload_url"], but the sync handler unconditionally
overwrites it with api_base (UUID-1). This causes the returned
file_id to point to a non-existent S3 key.

Fix: only set upload_url to api_base when transform_create_file_request
has not already set it, preserving the Bedrock provider's value.

Closes BerriAI#21546

* feat(semantic-cache): support configurable vector dimensions for Qdrant (BerriAI#21649)

Add vector_size parameter to QdrantSemanticCache and expose it through
the Cache facade as qdrant_semantic_cache_vector_size. This allows users
to use embedding models with dimensions other than the default 1536,
enabling cheaper/stronger models like Stella (1024d), bge-en-icl (4096d),
voyage, cohere, etc.

The parameter defaults to QDRANT_VECTOR_SIZE (env var or 1536) for
backward compatibility. When creating new collections, the configured
vector_size is used instead of the hardcoded constant.

Closes BerriAI#9377

* fix(utils): normalize camelCase thinking param keys to snake_case (BerriAI#21762)

Clients like OpenCode's @ai-sdk/openai-compatible send budgetTokens
(camelCase) instead of budget_tokens in the thinking parameter, causing
validation errors. Add early normalization in completion().

* feat: add optional digest mode for Slack alert types (BerriAI#21683)

Adds per-alert-type digest mode that aggregates duplicate alerts
within a configurable time window and emits a single summary message
with count, start/end timestamps.

Configuration via general_settings.alert_type_config:
  alert_type_config:
    llm_requests_hanging:
      digest: true
      digest_interval: 86400

Digest key: (alert_type, request_model, api_base)
Default interval: 24 hours
Window type: fixed interval

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add blog_posts.json and local backup

* feat: add GetBlogPosts utility with GitHub fetch and local fallback

Adds GetBlogPosts class that fetches blog posts from GitHub with a 1-hour
in-process TTL cache, validates the response, and falls back to the bundled
blog_posts_backup.json on any network or validation failure.

* test: add cache reset fixture and LITELLM_LOCAL_BLOG_POSTS test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GET /public/litellm_blog_posts endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: log fallback warning in blog posts endpoint and tighten test

* feat: add disable_show_blog to UISettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add useUISettings and useDisableShowBlog hooks

* fix: rename useUISettings to useUISettingsFlags to avoid naming collision

* fix: use existing useUISettings hook in useDisableShowBlog to avoid cache duplication

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown component with react-query and error/retry state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: enforce 5-post limit in BlogDropdown and add cap test

* fix: add retry, stable post key, enabled guard in BlogDropdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown to navbar after Docs link

* feat: add network_mock transport for benchmarking proxy overhead without real API calls

Intercepts at httpx transport layer so the full proxy path (auth, routing,
OpenAI SDK, response transformation) is exercised with zero-latency responses.
Activated via `litellm_settings: { network_mock: true }` in proxy config.

* Litellm dev 02 19 2026 p2 (BerriAI#21871)

* feat(ui/): new guardrails monitor 'demo

mock representation of what guardrails monitor looks like

* fix: ui updates

* style(ui/): fix styling

* feat: enable running ai monitor on individual guardrails

* feat: add backend logic for guardrail monitoring

* fix(guardrails/usage_endpoints.py): fix usage dashboard

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo (BerriAI#21754)

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo

* fix(budget): update stale docstring on get_budget_reset_time

* fix: add missing return type annotations to iterator protocol methods in streaming_handler (BerriAI#21750)

* fix: add return type annotations to iterator protocol methods in streaming_handler

Add missing return type annotations to __iter__, __aiter__, __next__, and __anext__ methods in CustomStreamWrapper and related classes.

- __iter__(self) -> Iterator["ModelResponseStream"]
- __aiter__(self) -> AsyncIterator["ModelResponseStream"]
- __next__(self) -> "ModelResponseStream"
- __anext__(self) -> "ModelResponseStream"

Also adds AsyncIterator and Iterator to typing imports.

Fixes issue with PLR0915 noqa comments and ensures proper type checking support.
Related to: BerriAI#8304

* fix: add ruff PLR0915 noqa for files with too many statements

* Add gollem Go agent framework cookbook example (BerriAI#21747)

Show how to use gollem, a production Go agent framework, with
LiteLLM proxy for multi-provider LLM access including tool use
and streaming.

* fix: avoid mutating caller-owned dicts in SpendUpdateQueue aggregation (BerriAI#21742)

* fix(vertex_ai): enable context-1m-2025-08-07 beta header (BerriAI#21870)

* server root path regression doc

* fixing syntax

* fix: replace Zapier webhook with Google Form for survey submission (BerriAI#21621)

* Replace Zapier webhook with Google Form for survey submission

* Add back error logging for survey submission debugging

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "Merge pull request BerriAI#21140 from BerriAI/litellm_perf_user_api_key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.

* test_vertex_ai_gemini_2_5_pro_streaming

* UI new build

* fix rendering

* ui new build

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* release note docs

* docs

* adding image

* fix(vertex_ai): enable context-1m-2025-08-07 beta header

The `context-1m-2025-08-07` Anthropic beta header was set to `null` for vertex_ai,
causing it to be filtered out when users set `extra_headers: {anthropic-beta: context-1m-2025-08-07}`.

This prevented using Claude's 1M context window feature via Vertex AI, resulting in
`prompt is too long: 460500 tokens > 200000 maximum` errors.

Fixes BerriAI#21861

---------

Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "fix(vertex_ai): enable context-1m-2025-08-07 beta header (BerriAI#21870)" (BerriAI#21876)

This reverts commit bce078a.

* docs(ui): add pre-PR checklist to UI contributing guide

Add testing and build verification steps per maintainer feedback
from @yjiang-litellm. Contributors should run their related tests
per-file and ensure npm run build passes before opening PRs.

* Fix entries with fast and us/

* Add tests for fast and us

* Add support for Priority PayGo for vertex ai and gemini

* Add model pricing

* fix: ensure arrival_time is set before calculating queue time

* Fix: Anthropic model wildcard access issue

* Add incident report

* Add ability to see which model cost map is getting used

* Fix name of title

* Readd tpm limit

* State management fixes for CheckBatchCost

* Fix PR review comments

* State management fixes for CheckBatchCost - Address greptile comments

* fix mypy issues:

* Add Noma guardrails v2 based on custom guardrails (BerriAI#21400)

* Fix code qa issues

* Fix mypy issues

* Fix mypy issues

* Fix test_aaamodel_prices_and_context_window_json_is_valid

* fix: update calendly on repo

* fix(tests): use counter-based mock for time.time in prisma self-heal test

The test used a fixed side_effect list for time.time(), but the number
of calls varies by Python version, causing StopIteration on 3.12 and
AssertionError on 3.14. Replace with an infinite counter-based callable
and assert the timestamp was updated rather than checking for an exact
value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tests): use absolute path for model_prices JSON in validation test

The test used a relative path 'litellm/model_prices_and_context_window.json'
which only works when pytest runs from a specific working directory.
Use os.path based on __file__ to resolve the path reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update tests/test_litellm/test_utils.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(tests): use os.path instead of Path to avoid NameError

Path is not imported at module level. Use os.path.join which is already
available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* clean up mock transport: remove streaming, add defensive parsing

* docs: add Google GenAI SDK tutorial (JS & Python) (BerriAI#21885)

* docs: add Google GenAI SDK tutorial for JS and Python

Add tutorial for using Google's official GenAI SDK (@google/genai for JS,
google-genai for Python) with LiteLLM proxy. Covers pass-through and
native router endpoints, streaming, multi-turn chat, and multi-provider
routing via model_group_alias. Also updates pass-through docs to use the
new SDK replacing the deprecated @google/generative-ai.

* fix(docs): correct Python SDK env var name in GenAI tutorial

GOOGLE_GENAI_API_KEY does not exist in the google-genai SDK.
The correct env var is GEMINI_API_KEY (or GOOGLE_API_KEY).
Also note that the Python SDK has no base URL env var.

* fix(docs): replace non-existent GOOGLE_GENAI_BASE_URL env var in interactions.md

The Python google-genai SDK does not read GOOGLE_GENAI_BASE_URL.
Use http_options={"base_url": "..."} in code instead.

* docs: add network mock benchmarking section

* docs: tweak benchmarks wording

* fix: add auth headers and empty latencies guard to benchmark script

* refactor: use method-level import for MockOpenAITransport

* fix: guard print_aggregate against empty latencies

* fix: add INCOMPLETE status to Interactions API enum and test

Google added INCOMPLETE to the Interactions API OpenAPI spec status enum.
Update both the Status3 enum in the SDK types and the test's expected
values to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Guardrail Monitor - measure guardrail reliability in prod  (BerriAI#21944)

* fix: fix log viewer for guardrail monitoring

* feat(ui/): fix rendering logs per guardrail

* fix: fix viewing logs on overview tab of guardrail

* fix: log viewer

* fix: fix naming to align with metric

* docs: add performance & reliability section to v1.81.14 release notes

* fix(tests): make RPM limit test sequential to avoid race condition

Concurrent requests via run_in_executor + asyncio.gather caused a race
condition where more requests slipped through the rate limiter than
expected, leading to flaky test failures (e.g. 3 successes instead of 2
with rpm_limit=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: Singapore guardrail policies (PDPA + MAS AI Risk Management) (BerriAI#21948)

* feat: Singapore PDPA PII protection guardrail policy template

Add Singapore Personal Data Protection Act (PDPA) guardrail support:

Regex patterns (patterns.json):
- sg_nric: NRIC/FIN detection ([STFGM] + 7 digits + checksum letter)
- sg_phone: Singapore phone numbers (+65/0065/65 prefix)
- sg_postal_code: 6-digit postal codes (contextual)
- passport_singapore: Passport numbers (E/K + 7 digits, contextual)
- sg_uen: Unique Entity Numbers (3 formats)
- sg_bank_account: Bank account numbers (dash format, contextual)

YAML policy templates (5 sub-guardrails):
- sg_pdpa_personal_identifiers: s.13 Consent
- sg_pdpa_sensitive_data: Advisory Guidelines
- sg_pdpa_do_not_call: Part IX DNC Registry
- sg_pdpa_data_transfer: s.26 overseas transfers
- sg_pdpa_profiling_automated_decisions: Model AI Governance Framework

Policy template entry in policy_templates.json with 9 guardrail definitions
(4 regex-based + 5 YAML conditional keyword matching).

Tests:
- test_sg_patterns.py: regex pattern unit tests
- test_sg_pdpa_guardrails.py: conditional keyword matching tests (100+ cases)

* feat: MAS AI Risk Management Guidelines guardrail policy template

Add Monetary Authority of Singapore (MAS) AI Risk Management Guidelines
guardrail support for financial institutions:

YAML policy templates (5 sub-guardrails):
- sg_mas_fairness_bias: Blocks discriminatory financial AI (credit/loans/insurance by protected attributes)
- sg_mas_transparency_explainability: Blocks opaque/unexplainable AI for consequential financial decisions
- sg_mas_human_oversight: Blocks fully automated financial decisions without human-in-the-loop
- sg_mas_data_governance: Blocks unauthorized sharing/mishandling of financial customer data
- sg_mas_model_security: Blocks adversarial attacks, model poisoning, inversion on financial AI

Policy template entry in policy_templates.json with 5 guardrail definitions.
Aligned with MAS FEAT Principles, Project MindForge, and NIST AI RMF.

Tests:
- test_sg_mas_ai_guardrails.py: conditional keyword matching tests (100+ cases)

* fix: address SG pattern review feedback

- Update NRIC lowercase test for IGNORECASE runtime behavior
- Add keyword context guard to sg_uen pattern to reduce false positives

* docs: clarify MAS AIRM timeline references

- Explicitly mark MAS AIRM as Nov 2025 consultation draft
- Add 2018 qualifier for FEAT principles in MAS policy descriptions
- Update MAS guardrail wording to avoid release-year ambiguity

* chore: commit resolved MAS policy conflicts

* test:

* chore:

* Add OpenAI Agents SDK tutorial with LiteLLM Proxy to docs  (BerriAI#21221)

* Add OpenAI Agents SDK tutorial to docs

* Update OpenAI Agents SDK tutorial to use LiteLLM environment variables

* Enhance OpenAI Agents SDK tutorial with built-in LiteLLM extension details and updated configuration steps. Adjust section headings for clarity and improve the flow of information regarding model setup and usage.

* adjust blog posts to fetch from github first

* feat(videos): add variant parameter to video content download (BerriAI#21955)

openai videos models support the features to download variants.
See more details here: https://developers.openai.com/api/docs/guides/video-generation#use-image-references.
Plumb variant (e.g. "thumbnail", "spritesheet") through the full
video content download chain: avideo_content → video_content →
video_content_handler → transform_video_content_request. OpenAI
appends ?variant=<value> to the GET URL; other providers accept
the parameter in their signature but ignore it.

* fixing path

* adjust blog post path

* Revert duplicate issue checker to text-based matching, remove duplicate PR workflow

Remove the Claude Code-powered duplicate PR detection workflow and revert
the duplicate issue checker back to wow-actions/potential-duplicates with
text similarity matching.

* ui changes

* adding tests

* adjust default aggregation threshold

* fix(videos): pass api_key from litellm_params to video remix handlers (BerriAI#21965)

video_remix_handler and async_video_remix_handler were not falling back
to litellm_params.api_key when the api_key parameter was None, causing
Authorization: Bearer None to be sent to the provider. This matches the
pattern already used by async_video_generation_handler.

* adding testing coverage + fixing flaky tests

* fix(ollama): thread api_base through get_model_info and add graceful fallback

When users pass api_base to litellm.completion() for Ollama, the model
info fetch (context window, function_calling support) was ignoring the
user's api_base and only reading OLLAMA_API_BASE env var or defaulting
to localhost:11434. This caused confusing errors in logs when Ollama
runs on a remote server.

Thread api_base from litellm_params through the get_model_info call
chain so OllamaConfig.get_model_info() uses the correct server. Also
return safe defaults instead of raising when the server is unreachable.

Fixes BerriAI#21967

---------

Co-authored-by: An Tang <ta@stripe.com>
Co-authored-by: janfrederickk <75388864+janfrederickk@users.noreply.github.com>
Co-authored-by: Zhenting Huang <3061613175@qq.com>
Co-authored-by: Darien Kindlund <darien@kindlund.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: Ryan Crabbe <rcrabbe@berkeley.edu>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: LeeJuOh <56071126+LeeJuOh@users.noreply.github.com>
Co-authored-by: Monesh Ram <31161039+WhoisMonesh@users.noreply.github.com>
Co-authored-by: Trevor Prater <trevor.prater@gmail.com>
Co-authored-by: The Mavik <179817126+themavik@users.noreply.github.com>
Co-authored-by: Edwin Isac <33712823+edwiniac@users.noreply.github.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Harshit Jain <harshitjain0562@gmail.com>
Co-authored-by: Harshit Jain <48647625+Harshit28j@users.noreply.github.com>
Co-authored-by: Ephrim Stanley <ephrim.stanley@point72.com>
Co-authored-by: TomAlon <tom@noma.security>
Co-authored-by: Julio Quinteros Pro <jquinter@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Ron Zhong <ron-zhong@hotmail.com>
Co-authored-by: Arindam Majumder <109217591+Arindam200@users.noreply.github.com>
Co-authored-by: Lei Nie <lenie@quora.com>
damhau pushed a commit to damhau/litellm that referenced this pull request Feb 26, 2026
…voke (BerriAI#21964)

* auth_with_role_name add region_name arg for cross-account sts

* update tests to include case with aws_region_name for _auth_with_aws_role

* Only pass region_name to STS client when aws_region_name is set

* Add optional aws_sts_endpoint to _auth_with_aws_role

* Parametrize ambient-credentials test for no opts, region_name, and aws_sts_endpoint

* consistently passing region and endpoint args into explicit credentials irsa

* fix env var leakage

* fix: bedrock openai-compatible imported-model should also have model arn encoded

* feat: show proxy url in ModelHub (BerriAI#21660)

* fix(bedrock): correct modelInput format for Converse API batch models (BerriAI#21656)

* fix(proxy): add model_ids param to access group endpoints for precise deployment tagging (BerriAI#21655)

POST /access_group/new and PUT /access_group/{name}/update now accept an
optional model_ids list that targets specific deployments by their unique
model_id, instead of tagging every deployment that shares a model_name.

When model_ids is provided it takes priority over model_names, giving
API callers the same single-deployment precision that the UI already has
via PATCH /model/{model_id}/update.

Backward compatible: model_names continues to work as before.

Closes BerriAI#21544

* feat(proxy): add custom favicon support\n\nAdd ability to configure a custom favicon for the litellm proxy UI.\n\n- Add favicon_url field to UIThemeConfig model\n- Add LITELLM_FAVICON_URL env var support\n- Add /get_favicon endpoint to serve custom favicons\n- Update ThemeContext to dynamically set favicon\n- Add favicon URL input to UI theme settings page\n- Add comprehensive tests\n\nCloses BerriAI#8323 (BerriAI#21653)

* fix(bedrock): prevent double UUID in create_file S3 key (BerriAI#21650)

In create_file for Bedrock, get_complete_file_url is called twice:
once in the sync handler (generating UUID-1 for api_base) and once
inside transform_create_file_request (generating UUID-2 for the
actual S3 upload). The Bedrock provider correctly writes UUID-2 into
litellm_params["upload_url"], but the sync handler unconditionally
overwrites it with api_base (UUID-1). This causes the returned
file_id to point to a non-existent S3 key.

Fix: only set upload_url to api_base when transform_create_file_request
has not already set it, preserving the Bedrock provider's value.

Closes BerriAI#21546

* feat(semantic-cache): support configurable vector dimensions for Qdrant (BerriAI#21649)

Add vector_size parameter to QdrantSemanticCache and expose it through
the Cache facade as qdrant_semantic_cache_vector_size. This allows users
to use embedding models with dimensions other than the default 1536,
enabling cheaper/stronger models like Stella (1024d), bge-en-icl (4096d),
voyage, cohere, etc.

The parameter defaults to QDRANT_VECTOR_SIZE (env var or 1536) for
backward compatibility. When creating new collections, the configured
vector_size is used instead of the hardcoded constant.

Closes BerriAI#9377

* fix(utils): normalize camelCase thinking param keys to snake_case (BerriAI#21762)

Clients like OpenCode's @ai-sdk/openai-compatible send budgetTokens
(camelCase) instead of budget_tokens in the thinking parameter, causing
validation errors. Add early normalization in completion().

* feat: add optional digest mode for Slack alert types (BerriAI#21683)

Adds per-alert-type digest mode that aggregates duplicate alerts
within a configurable time window and emits a single summary message
with count, start/end timestamps.

Configuration via general_settings.alert_type_config:
  alert_type_config:
    llm_requests_hanging:
      digest: true
      digest_interval: 86400

Digest key: (alert_type, request_model, api_base)
Default interval: 24 hours
Window type: fixed interval

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add blog_posts.json and local backup

* feat: add GetBlogPosts utility with GitHub fetch and local fallback

Adds GetBlogPosts class that fetches blog posts from GitHub with a 1-hour
in-process TTL cache, validates the response, and falls back to the bundled
blog_posts_backup.json on any network or validation failure.

* test: add cache reset fixture and LITELLM_LOCAL_BLOG_POSTS test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add GET /public/litellm_blog_posts endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: log fallback warning in blog posts endpoint and tighten test

* feat: add disable_show_blog to UISettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add useUISettings and useDisableShowBlog hooks

* fix: rename useUISettings to useUISettingsFlags to avoid naming collision

* fix: use existing useUISettings hook in useDisableShowBlog to avoid cache duplication

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown component with react-query and error/retry state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: enforce 5-post limit in BlogDropdown and add cap test

* fix: add retry, stable post key, enabled guard in BlogDropdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add BlogDropdown to navbar after Docs link

* feat: add network_mock transport for benchmarking proxy overhead without real API calls

Intercepts at httpx transport layer so the full proxy path (auth, routing,
OpenAI SDK, response transformation) is exercised with zero-latency responses.
Activated via `litellm_settings: { network_mock: true }` in proxy config.

* Litellm dev 02 19 2026 p2 (BerriAI#21871)

* feat(ui/): new guardrails monitor 'demo

mock representation of what guardrails monitor looks like

* fix: ui updates

* style(ui/): fix styling

* feat: enable running ai monitor on individual guardrails

* feat: add backend logic for guardrail monitoring

* fix(guardrails/usage_endpoints.py): fix usage dashboard

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo (BerriAI#21754)

* fix(budget): fix timezone config lookup and replace hardcoded timezone map with ZoneInfo

* fix(budget): update stale docstring on get_budget_reset_time

* fix: add missing return type annotations to iterator protocol methods in streaming_handler (BerriAI#21750)

* fix: add return type annotations to iterator protocol methods in streaming_handler

Add missing return type annotations to __iter__, __aiter__, __next__, and __anext__ methods in CustomStreamWrapper and related classes.

- __iter__(self) -> Iterator["ModelResponseStream"]
- __aiter__(self) -> AsyncIterator["ModelResponseStream"]
- __next__(self) -> "ModelResponseStream"
- __anext__(self) -> "ModelResponseStream"

Also adds AsyncIterator and Iterator to typing imports.

Fixes issue with PLR0915 noqa comments and ensures proper type checking support.
Related to: BerriAI#8304

* fix: add ruff PLR0915 noqa for files with too many statements

* Add gollem Go agent framework cookbook example (BerriAI#21747)

Show how to use gollem, a production Go agent framework, with
LiteLLM proxy for multi-provider LLM access including tool use
and streaming.

* fix: avoid mutating caller-owned dicts in SpendUpdateQueue aggregation (BerriAI#21742)

* fix(vertex_ai): enable context-1m-2025-08-07 beta header (BerriAI#21870)

* server root path regression doc

* fixing syntax

* fix: replace Zapier webhook with Google Form for survey submission (BerriAI#21621)

* Replace Zapier webhook with Google Form for survey submission

* Add back error logging for survey submission debugging

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "Merge pull request BerriAI#21140 from BerriAI/litellm_perf_user_api_key_auth"

This reverts commit 0e1db3f, reversing
changes made to 7e2d6f2.

* test_vertex_ai_gemini_2_5_pro_streaming

* UI new build

* fix rendering

* ui new build

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* docs fix

* release note docs

* docs

* adding image

* fix(vertex_ai): enable context-1m-2025-08-07 beta header

The `context-1m-2025-08-07` Anthropic beta header was set to `null` for vertex_ai,
causing it to be filtered out when users set `extra_headers: {anthropic-beta: context-1m-2025-08-07}`.

This prevented using Claude's 1M context window feature via Vertex AI, resulting in
`prompt is too long: 460500 tokens > 200000 maximum` errors.

Fixes BerriAI#21861

---------

Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>

* Revert "fix(vertex_ai): enable context-1m-2025-08-07 beta header (BerriAI#21870)" (BerriAI#21876)

This reverts commit bce078a.

* docs(ui): add pre-PR checklist to UI contributing guide

Add testing and build verification steps per maintainer feedback
from @yjiang-litellm. Contributors should run their related tests
per-file and ensure npm run build passes before opening PRs.

* Fix entries with fast and us/

* Add tests for fast and us

* Add support for Priority PayGo for vertex ai and gemini

* Add model pricing

* fix: ensure arrival_time is set before calculating queue time

* Fix: Anthropic model wildcard access issue

* Add incident report

* Add ability to see which model cost map is getting used

* Fix name of title

* Readd tpm limit

* State management fixes for CheckBatchCost

* Fix PR review comments

* State management fixes for CheckBatchCost - Address greptile comments

* fix mypy issues:

* Add Noma guardrails v2 based on custom guardrails (BerriAI#21400)

* Fix code qa issues

* Fix mypy issues

* Fix mypy issues

* Fix test_aaamodel_prices_and_context_window_json_is_valid

* fix: update calendly on repo

* fix(tests): use counter-based mock for time.time in prisma self-heal test

The test used a fixed side_effect list for time.time(), but the number
of calls varies by Python version, causing StopIteration on 3.12 and
AssertionError on 3.14. Replace with an infinite counter-based callable
and assert the timestamp was updated rather than checking for an exact
value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tests): use absolute path for model_prices JSON in validation test

The test used a relative path 'litellm/model_prices_and_context_window.json'
which only works when pytest runs from a specific working directory.
Use os.path based on __file__ to resolve the path reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update tests/test_litellm/test_utils.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(tests): use os.path instead of Path to avoid NameError

Path is not imported at module level. Use os.path.join which is already
available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* clean up mock transport: remove streaming, add defensive parsing

* docs: add Google GenAI SDK tutorial (JS & Python) (BerriAI#21885)

* docs: add Google GenAI SDK tutorial for JS and Python

Add tutorial for using Google's official GenAI SDK (@google/genai for JS,
google-genai for Python) with LiteLLM proxy. Covers pass-through and
native router endpoints, streaming, multi-turn chat, and multi-provider
routing via model_group_alias. Also updates pass-through docs to use the
new SDK replacing the deprecated @google/generative-ai.

* fix(docs): correct Python SDK env var name in GenAI tutorial

GOOGLE_GENAI_API_KEY does not exist in the google-genai SDK.
The correct env var is GEMINI_API_KEY (or GOOGLE_API_KEY).
Also note that the Python SDK has no base URL env var.

* fix(docs): replace non-existent GOOGLE_GENAI_BASE_URL env var in interactions.md

The Python google-genai SDK does not read GOOGLE_GENAI_BASE_URL.
Use http_options={"base_url": "..."} in code instead.

* docs: add network mock benchmarking section

* docs: tweak benchmarks wording

* fix: add auth headers and empty latencies guard to benchmark script

* refactor: use method-level import for MockOpenAITransport

* fix: guard print_aggregate against empty latencies

* fix: add INCOMPLETE status to Interactions API enum and test

Google added INCOMPLETE to the Interactions API OpenAPI spec status enum.
Update both the Status3 enum in the SDK types and the test's expected
values to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Guardrail Monitor - measure guardrail reliability in prod  (BerriAI#21944)

* fix: fix log viewer for guardrail monitoring

* feat(ui/): fix rendering logs per guardrail

* fix: fix viewing logs on overview tab of guardrail

* fix: log viewer

* fix: fix naming to align with metric

* docs: add performance & reliability section to v1.81.14 release notes

* fix(tests): make RPM limit test sequential to avoid race condition

Concurrent requests via run_in_executor + asyncio.gather caused a race
condition where more requests slipped through the rate limiter than
expected, leading to flaky test failures (e.g. 3 successes instead of 2
with rpm_limit=2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: Singapore guardrail policies (PDPA + MAS AI Risk Management) (BerriAI#21948)

* feat: Singapore PDPA PII protection guardrail policy template

Add Singapore Personal Data Protection Act (PDPA) guardrail support:

Regex patterns (patterns.json):
- sg_nric: NRIC/FIN detection ([STFGM] + 7 digits + checksum letter)
- sg_phone: Singapore phone numbers (+65/0065/65 prefix)
- sg_postal_code: 6-digit postal codes (contextual)
- passport_singapore: Passport numbers (E/K + 7 digits, contextual)
- sg_uen: Unique Entity Numbers (3 formats)
- sg_bank_account: Bank account numbers (dash format, contextual)

YAML policy templates (5 sub-guardrails):
- sg_pdpa_personal_identifiers: s.13 Consent
- sg_pdpa_sensitive_data: Advisory Guidelines
- sg_pdpa_do_not_call: Part IX DNC Registry
- sg_pdpa_data_transfer: s.26 overseas transfers
- sg_pdpa_profiling_automated_decisions: Model AI Governance Framework

Policy template entry in policy_templates.json with 9 guardrail definitions
(4 regex-based + 5 YAML conditional keyword matching).

Tests:
- test_sg_patterns.py: regex pattern unit tests
- test_sg_pdpa_guardrails.py: conditional keyword matching tests (100+ cases)

* feat: MAS AI Risk Management Guidelines guardrail policy template

Add Monetary Authority of Singapore (MAS) AI Risk Management Guidelines
guardrail support for financial institutions:

YAML policy templates (5 sub-guardrails):
- sg_mas_fairness_bias: Blocks discriminatory financial AI (credit/loans/insurance by protected attributes)
- sg_mas_transparency_explainability: Blocks opaque/unexplainable AI for consequential financial decisions
- sg_mas_human_oversight: Blocks fully automated financial decisions without human-in-the-loop
- sg_mas_data_governance: Blocks unauthorized sharing/mishandling of financial customer data
- sg_mas_model_security: Blocks adversarial attacks, model poisoning, inversion on financial AI

Policy template entry in policy_templates.json with 5 guardrail definitions.
Aligned with MAS FEAT Principles, Project MindForge, and NIST AI RMF.

Tests:
- test_sg_mas_ai_guardrails.py: conditional keyword matching tests (100+ cases)

* fix: address SG pattern review feedback

- Update NRIC lowercase test for IGNORECASE runtime behavior
- Add keyword context guard to sg_uen pattern to reduce false positives

* docs: clarify MAS AIRM timeline references

- Explicitly mark MAS AIRM as Nov 2025 consultation draft
- Add 2018 qualifier for FEAT principles in MAS policy descriptions
- Update MAS guardrail wording to avoid release-year ambiguity

* chore: commit resolved MAS policy conflicts

* test:

* chore:

* Add OpenAI Agents SDK tutorial with LiteLLM Proxy to docs  (BerriAI#21221)

* Add OpenAI Agents SDK tutorial to docs

* Update OpenAI Agents SDK tutorial to use LiteLLM environment variables

* Enhance OpenAI Agents SDK tutorial with built-in LiteLLM extension details and updated configuration steps. Adjust section headings for clarity and improve the flow of information regarding model setup and usage.

* adjust blog posts to fetch from github first

* feat(videos): add variant parameter to video content download (BerriAI#21955)

openai videos models support the features to download variants.
See more details here: https://developers.openai.com/api/docs/guides/video-generation#use-image-references.
Plumb variant (e.g. "thumbnail", "spritesheet") through the full
video content download chain: avideo_content → video_content →
video_content_handler → transform_video_content_request. OpenAI
appends ?variant=<value> to the GET URL; other providers accept
the parameter in their signature but ignore it.

* fixing path

* adjust blog post path

* Revert duplicate issue checker to text-based matching, remove duplicate PR workflow

Remove the Claude Code-powered duplicate PR detection workflow and revert
the duplicate issue checker back to wow-actions/potential-duplicates with
text similarity matching.

* ui changes

* adding tests

* fix(anthropic): sanitize tool_use IDs in assistant messages

Apply _sanitize_anthropic_tool_use_id to tool_use blocks in
convert_to_anthropic_tool_invoke, not just tool_result blocks.
IDs from external frameworks (e.g. MiniMax) may contain characters
like colons that violate Anthropic's ^[a-zA-Z0-9_-]+$ pattern.

Adds test for invalid ID sanitization in tool_use blocks.

---------

Co-authored-by: An Tang <ta@stripe.com>
Co-authored-by: janfrederickk <75388864+janfrederickk@users.noreply.github.com>
Co-authored-by: Zhenting Huang <3061613175@qq.com>
Co-authored-by: Cesar Garcia <128240629+Chesars@users.noreply.github.com>
Co-authored-by: Darien Kindlund <darien@kindlund.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: yuneng-jiang <yuneng.jiang@gmail.com>
Co-authored-by: Ryan Crabbe <rcrabbe@berkeley.edu>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: LeeJuOh <56071126+LeeJuOh@users.noreply.github.com>
Co-authored-by: Monesh Ram <31161039+WhoisMonesh@users.noreply.github.com>
Co-authored-by: Trevor Prater <trevor.prater@gmail.com>
Co-authored-by: The Mavik <179817126+themavik@users.noreply.github.com>
Co-authored-by: Edwin Isac <33712823+edwiniac@users.noreply.github.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Chesars <cesarponce19544@gmail.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Harshit Jain <harshitjain0562@gmail.com>
Co-authored-by: Harshit Jain <48647625+Harshit28j@users.noreply.github.com>
Co-authored-by: Ephrim Stanley <ephrim.stanley@point72.com>
Co-authored-by: TomAlon <tom@noma.security>
Co-authored-by: Julio Quinteros Pro <jquinter@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Ron Zhong <ron-zhong@hotmail.com>
Co-authored-by: Arindam Majumder <109217591+Arindam200@users.noreply.github.com>
Co-authored-by: Lei Nie <lenie@quora.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant