fix: prioritize tool_calls over text when available_functions is None#4879
fix: prioritize tool_calls over text when available_functions is None#4879education-01 wants to merge 1 commit intocrewAIInc:mainfrom
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| # --- 5) If there are tool calls but no available functions, return the tool calls | ||
| # This allows the caller (e.g., executor) to handle tool execution | ||
| if tool_calls and not available_functions: | ||
| return tool_calls |
There was a problem hiding this comment.
Missing LLMCallCompletedEvent when returning tool_calls with text
Low Severity
When both tool_calls and text_response are present with available_functions=None, the new early-return path at return tool_calls skips emitting LLMCallCompletedEvent. Previously this scenario took the text-response branch, which did emit the event. Since LLMCallStartedEvent is always emitted by the caller, this creates an unpaired start event. The event listener uses LLMCallCompletedEvent to call handle_llm_stream_completed(), which resets formatter state like _is_streaming and stops the live display — so skipping it could leave the console formatter in an inconsistent state.


Fixes #4788
Problem
When LLM returns both text and tool_calls simultaneously, and executor passes available_functions=None to get_llm_response, the current logic returns text instead of tool_calls. This causes native tool calls to be discarded.
Root Cause
In llm.py, the branch order was:
When both text and tool_calls exist with available_functions=None, branch 1 fires first, and branch 2 is never reached.
Fix
Reorder to prioritize tool_calls:
Changes
Testing
Added two unit tests:
Both verify that tool_calls are returned when available_functions=None, even when text content is present.
Note
Low Risk
Low risk logic reordering in LiteLLM non-streaming sync/async paths; behavior changes only when responses include both
contentandtool_callsandavailable_functionsisNone/empty.Overview
Fixes LiteLLM non-streaming response handling so that when an LLM returns both
contentandtool_callsandavailable_functionsis not provided, the LLM returns the rawtool_callsinstead of discarding them by returning text.Adds sync and async regression tests (mocking
litellm.completion/litellm.acompletion) to assertLLM.call/LLM.acallprefertool_callsover text in this scenario.Written by Cursor Bugbot for commit 684de7e. This will update automatically on new commits. Configure here.