litellm oss branch - #26386
Conversation
|
All review comments resolved — no active issues remaining. Status: 0 open Posted by Veria AI · 2026-04-27T06:02:32.365Z |
Greptile SummaryThis PR bundles several independent changes: (1) the stated Bedrock TTL fix — Confidence Score: 4/5Safe to merge with one low-severity observability gap in the new XecGuard guardrail; the core Bedrock TTL fix is correct and well-tested. No P0 findings. One P2 in the new XecGuard async_logging_hook (silent data loss in observability when standard_logging_object is absent). Previously flagged P1s in pass_through_endpoints.py remain unaddressed but were already reviewed. Score is 4 rather than 5 because those open P1 threads are still present in the changeset. litellm/proxy/pass_through_endpoints/pass_through_endpoints.py (open P1 findings from prior review), litellm/proxy/guardrails/guardrail_hooks/xecguard/xecguard.py (async_logging_hook guard).
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/xecguard/xecguard.py | New XecGuard guardrail integration; async_logging_hook accesses kwargs["standard_logging_object"] without a key/type guard, silently dropping guardrail observability data when that key is absent. |
| litellm/proxy/pass_through_endpoints/pass_through_endpoints.py | Adds post-call guardrail invocation for pass-through responses and a ModifyResponseException handler; response body may be lost for logging if the hook returns non-dict (flagged in prior reviews). |
| litellm/litellm_core_utils/prompt_templates/factory.py | Adds model param to add_cache_point_tool_block and _bedrock_tools_pt so TTL is preserved for Claude 4.5+ on the Converse path, mirroring the existing _get_cache_point_block behaviour. |
| litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py | Extends _remove_ttl_from_cache_control to also sanitize cache_control on tool definitions, matching the system/messages handling and fixing the non-increasing TTL ordering error on the Invoke path. |
| litellm/exceptions.py | Moves ModifyResponseException from custom_guardrail.py to exceptions.py so it can be imported by the pass-through endpoint without a circular dependency. |
| litellm/llms/predibase/chat/handler.py | Removes ~160 lines of output_parser/process_response logic from the handler, moving it into transformation.py following the provider separation pattern. |
| litellm/llms/ollama/chat/transformation.py | Fixes tool_calls assignment by writing to ollama_message instead of mutating the input message m, and adds tool_call_id pass-through. |
| litellm/router.py | Propagates input_cost_per_token and output_cost_per_token from db_model_info into ModelMapInfo instead of hardcoding None. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Bedrock request with cache_control TTL] --> B{Path?}
B -->|Converse| C["_bedrock_tools_pt(tools, model=model)"]
C --> D["add_cache_point_tool_block(tool, model=model)"]
D --> E{is_claude_4_5_on_bedrock?}
E -->|Yes + ttl in 5m/1h| F[Preserve TTL in cachePoint block]
E -->|No| G[Drop TTL — default cachePoint]
B -->|Invoke / Messages| H["_remove_ttl_from_cache_control()"]
H --> I[Sanitize tools cache_control]
H --> J[Sanitize system cache_control]
H --> K[Sanitize messages cache_control]
I --> L{Claude 4.5+?}
J --> L
K --> L
L -->|Yes| M[Keep ttl if valid 5m/1h]
L -->|No| N[Remove ttl]
subgraph Pass-through guardrail flow
P[Pass-through response] --> Q{response_body != None and guardrails_to_run?}
Q -->|Yes| R[post_call_success_hook with enriched hook_data]
R -->|Returns dict| S[Re-encode content + strip content-length]
R -->|Returns non-dict| T[Use original content]
R -->|Raises ModifyResponseException| U[Return 200 with error JSON]
end
Reviews (8): Last reviewed commit: "fix black issues" | Re-trigger Greptile
| if ( | ||
| ttl in ["5m", "1h"] | ||
| and model is not None | ||
| and is_claude_4_5_on_bedrock(model) | ||
| ): | ||
| cache_point_block["ttl"] = ttl |
There was a problem hiding this comment.
Hardcoded model-specific flag — violates project rule
is_claude_4_5_on_bedrock is a hardcoded list of model-name patterns. The project policy requires model capability flags to live in model_prices_and_context_window.json and be read via get_model_info, so that adding a new Claude 4.x model that supports TTL does not require a code change or a LiteLLM upgrade. The analogous _get_cache_point_block path already calls the same hardcoded function, so this PR extends the pattern rather than introducing it — but each new call site makes the problem harder to fix later.
Rule Used: What: Do not hardcode model-specific flags in the ... (source)
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
|
| hook_data = dict(_parsed_body or {}) | ||
| existing_metadata = hook_data.get("metadata") | ||
| if not isinstance(existing_metadata, dict): | ||
| existing_metadata = {} | ||
| hook_data["metadata"] = { | ||
| **existing_metadata, | ||
| "guardrails": guardrails_to_run, | ||
| } | ||
| response_body = await proxy_logging_obj.post_call_success_hook( | ||
| data=hook_data, | ||
| user_api_key_dict=user_api_key_dict, | ||
| response=response_body, # type: ignore[arg-type] |
There was a problem hiding this comment.
litellm_logging_obj missing from hook_data — unified_guardrail fallback is dead code
The unified_guardrail.async_post_call_success_hook added a fallback in this PR to resolve call_type via data.get("litellm_logging_obj") for pass-through requests. However, hook_data is built solely from _parsed_body (the raw request body), so litellm_logging_obj is never present there. The fallback will always short-circuit with litellm_logging_obj is not None → False, meaning that for routes where neither get_call_types_for_route nor _infer_call_type resolves a call_type, the guardrail silently returns without running — even though the pass-through endpoint's logging object is available in scope as logging_obj.
hook_data = dict(_parsed_body or {})
# add this so the unified_guardrail fallback can detect pass_through call_type
hook_data["litellm_logging_obj"] = logging_obj…5855) Bedrock enforces non-increasing TTL ordering across cache_control blocks (tools → system → messages). The tool cache_control TTL was being unconditionally dropped to the default 5m, while system blocks preserved the user-specified TTL for Claude 4.5+ models. This mismatch caused "a ttl='1h' block must not come after a ttl='5m' block" errors when users set ttl='1h' on both tools and system. Converse path: add_cache_point_tool_block() now accepts a model param and preserves TTL for Claude 4.5+, matching _get_cache_point_block(). Invoke path: _remove_ttl_from_cache_control() now also processes tools (was only processing system and messages). Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onses (#20270) (#26262) * fix(proxy): invoke post-call guardrails on pass-through endpoint responses (#20270) Wire post_call_success_hook into non-streaming pass-through response path, gated on explicit guardrail config (opt-in only, no backwards-compat break). - Call post_call_success_hook after reading non-streaming response body - Build enriched hook_data with guardrails metadata and litellm_logging_obj at call site (avoids mutation of _parsed_body which is shared by logging) - Handle ModifyResponseException with provider-agnostic error envelope, post_call_failure_hook, and defensive try/except - Strip stale content-length when guardrail modifies response body - Move ModifyResponseException to litellm.exceptions to break cyclic import; re-export from custom_guardrail for backwards compat - Add call_type fallback in UnifiedLLMGuardrails for pass-through endpoints using CallTypes.pass_through.value enum * test: add unit tests for pass-through post-call guardrails 5 tests covering the post-call guardrail invocation on pass-through endpoints: - post_call_success_hook fires when guardrails configured - post_call_success_hook skipped when no guardrails (backwards compat) - ModifyResponseException returns 200 with provider-agnostic error - UnifiedLLMGuardrails resolves call_type from logging_obj for pass-through - ModifyResponseException re-export from custom_guardrail stays in sync
…n fallback path (#25888)
…#26122) tool_calls on assistant messages were translated to OllamaToolCall format but never copied into the outgoing OllamaChatCompletionMessage, so Ollama received {role: assistant, content: ''} with no tool_calls. The model then had no record of having made a tool call, causing it to re-issue the identical call on every turn (infinite loop). Similarly, tool_call_id on role:tool messages was silently dropped. Ollama uses this field to resolve the tool name from conversation history. Also add tool_call_id to OllamaChatCompletionMessage TypedDict. Fixes #26094
cd88dde to
c014bfa
Compare
|
Was deleting the |
litellm oss branch
…5855)
Bedrock enforces non-increasing TTL ordering across cache_control blocks (tools → system → messages). The tool cache_control TTL was being unconditionally dropped to the default 5m, while system blocks preserved the user-specified TTL for Claude 4.5+ models. This mismatch caused "a ttl='1h' block must not come after a ttl='5m' block" errors when users set ttl='1h' on both tools and system.
Converse path: add_cache_point_tool_block() now accepts a model param and preserves TTL for Claude 4.5+, matching _get_cache_point_block().
Invoke path: _remove_ttl_from_cache_control() now also processes tools (was only processing system and messages).
Relevant issues
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
CI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Screenshots / Proof of Fix
Type
🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test
Changes