fix(websearch): wrap agentic loop response in fake stream for streaming requests - #27449
fix(websearch): wrap agentic loop response in fake stream for streaming requests#27449vokako wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR fixes a bug where streaming requests routed through
Confidence Score: 4/5The change is safe to merge; it fixes a clearly broken streaming path without touching any other request flow. All four agentic-loop exit paths are correctly guarded. The isinstance(response, dict) check prevents double-wrapping when a recursive agentic iteration already returned an iterator. The only gap is that the no-loop-ran fallback at the bottom of _call_agentic_completion_hooks still inlines the same detection logic instead of delegating to the new helper, leaving duplicate code that could drift. The inline duplication in _call_agentic_completion_hooks around lines 4929-4966 should be cleaned up.
|
| Filename | Overview |
|---|---|
| litellm/llms/custom_httpx/llm_http_handler.py | Adds _maybe_wrap_in_fake_stream() helper and applies it to all four agentic-loop return paths; the existing no-loop path at the bottom of the function still inlines the same logic rather than delegating to the helper. |
| tests/test_litellm/integrations/websearch_interception/test_websearch_streaming_wrap.py | New unit tests for _maybe_wrap_in_fake_stream; all four branches covered, mock-only with no real network calls. |
Comments Outside Diff (1)
-
litellm/llms/custom_httpx/llm_http_handler.py, line 4929-4966 (link)The "no agentic loop ran" fallback at the end of
_call_agentic_completion_hooksduplicates the same flag-check and wrapping logic that was just extracted into_maybe_wrap_in_fake_stream. Using the helper here too would remove the duplication and make future maintenance easier — any change to the wrapping logic only needs to happen in one place.
Reviews (1): Last reviewed commit: "fix(websearch): wrap agentic loop respon..." | Re-trigger Greptile
14c0b6a to
fe1ff75
Compare
…ng requests When websearch_interception converts stream=True to stream=False internally, the agentic loop returns a plain dict. Previously this dict was returned directly to the client expecting SSE events, resulting in empty streams. Added _maybe_wrap_in_fake_stream() which checks the websearch_interception_converted_stream flag and wraps dict responses in FakeAnthropicMessagesStreamIterator. Applied to all return paths in _call_agentic_completion_hooks: - async_run_agentic_loop (legacy path) - _execute_anthropic_agentic_plan (plan-based path) - plan.response_override - plan.terminate Includes unit tests for _maybe_wrap_in_fake_stream().
fe1ff75 to
c3b5e07
Compare
|
This has been merged. We've credited you for this change. Thank you so much for your contribution! |
Summary
When
websearch_interceptionis enabled and a client sends a streaming request via/v1/messages, the handler convertsstream=Truetostream=Falseinternally to execute the search. After the agentic loop completes, the non-streaming dict response was returned directly to the client expecting SSE events, resulting in empty streams.Root Cause
In
_call_agentic_completion_hooks(), theFakeAnthropicMessagesStreamIteratorwrapping code only executes when no agentic loop ran. When the agentic loop does run, all return paths return the dict directly without wrapping.Fix
Added
_maybe_wrap_in_fake_stream()helper that checks thewebsearch_interception_converted_streamflag and wraps dict responses inFakeAnthropicMessagesStreamIterator. Applied to all return paths in_call_agentic_completion_hooks:async_run_agentic_loop(legacy path)_execute_anthropic_agentic_plan(plan-based path)plan.response_overrideplan.terminateTesting
_maybe_wrap_in_fake_stream()client.messages.stream()+ websearch tool:Changes
litellm/llms/custom_httpx/llm_http_handler.py: Added_maybe_wrap_in_fake_stream()method, wrapped all agentic loop return pathstests/test_litellm/integrations/websearch_interception/test_websearch_streaming_wrap.py: Unit tests