From 6f807fd42a10794c9a5603f3dbc55fae930af414 Mon Sep 17 00:00:00 2001 From: Vineeth Sai Date: Wed, 21 Oct 2026 09:31:24 -0700 Subject: [PATCH] test(agentic loop): pin the converted-stream replay when no tool is called The converted-stream fix landed upstream and the tool-call follow-up is covered. The path where the model answers without a tool call and no callback gates ends in _converted_stream_replay, and replacing that with return None passes every existing test. Add a case per interception prefix that expects a CustomStreamWrapper iterating back to the original reply. --- .../test_chat_completion_agentic_loop.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/unit/litellm_core_utils/test_chat_completion_agentic_loop.py b/tests/unit/litellm_core_utils/test_chat_completion_agentic_loop.py index 3cbc3591009..533095d8ebe 100644 --- a/tests/unit/litellm_core_utils/test_chat_completion_agentic_loop.py +++ b/tests/unit/litellm_core_utils/test_chat_completion_agentic_loop.py @@ -519,3 +519,40 @@ async def test_converted_stream_replays_the_final_answer_with_the_requested_usag if include_usage else [] ) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "prefix", (WEBSEARCH_INTERCEPTION_PREFIX, CODE_INTERPRETER_INTERCEPTION_PREFIX, HEADROOM_INTERCEPTION_PREFIX) +) +async def test_converted_stream_replays_the_original_reply_when_no_tool_is_called( + monkeypatch: pytest.MonkeyPatch, prefix: str +): + """A streamed request that was converted to a non-streaming call still gets a + stream back when the model answers without a tool call and no callback gates.""" + monkeypatch.setattr(litellm, "callbacks", []) + logging_obj: Final = Logging( + model="gpt-4o", + messages=[{"role": "user", "content": "hello"}], + stream=False, + call_type="acompletion", + start_time=datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc), + litellm_call_id="call-no-tool", + function_id="fn-no-tool", + ) + + result: Final = await maybe_run_chat_completion_agentic_loop( + response=_plain_model_response("no tool needed"), + model="gpt-4o", + messages=[{"role": "user", "content": "hello"}], + optional_params={}, + kwargs={f"{prefix}_converted_stream": True}, + logging_obj=logging_obj, + custom_llm_provider="azure", + stream=False, + ) + + assert isinstance(result, CustomStreamWrapper) + chunks: Final = [chunk async for chunk in result] + content: Final = "".join(chunk.choices[0].delta.content or "" for chunk in chunks if chunk.choices) + assert content == "no tool needed"