fix: only pass tools parameter when tools are available

This fixes the CI test failures by only passing the tools parameter to
llm.call() and llm.acall() when tools are actually available. This
maintains backward compatibility with existing code that checks
'tools' in kwargs to determine if tools were provided.

The previous commit always passed tools=None, which caused tests that
check 'tools' in kwargs to fail because the key was always present.

Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
Devin AI
2026-01-14 22:54:18 +00:00
parent d97d58d2c3
commit 7fb8999545
2 changed files with 53 additions and 28 deletions

View File

@@ -310,14 +310,25 @@ def get_llm_response(
tools = _extract_tools_from_context(executor_context)
try:
answer = llm.call(
messages,
tools=tools,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
# Only pass tools parameter if tools are available to maintain backward compatibility
# with code that checks "tools" in kwargs
if tools is not None:
answer = llm.call(
messages,
tools=tools,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
else:
answer = llm.call(
messages,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
except Exception as e:
raise e
if not answer:
@@ -368,14 +379,25 @@ async def aget_llm_response(
tools = _extract_tools_from_context(executor_context)
try:
answer = await llm.acall(
messages,
tools=tools,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
# Only pass tools parameter if tools are available to maintain backward compatibility
# with code that checks "tools" in kwargs
if tools is not None:
answer = await llm.acall(
messages,
tools=tools,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
else:
answer = await llm.acall(
messages,
callbacks=callbacks,
from_task=from_task,
from_agent=from_agent, # type: ignore[arg-type]
response_model=response_model,
)
except Exception as e:
raise e
if not answer:

View File

@@ -190,8 +190,8 @@ class TestGetLlmResponse:
assert len(call_kwargs["tools"]) == 1
assert call_kwargs["tools"][0]["name"] == "test_tool"
def test_passes_none_tools_when_no_context(self, mock_llm, mock_printer):
"""Test that tools=None is passed when no executor_context."""
def test_does_not_pass_tools_when_no_context(self, mock_llm, mock_printer):
"""Test that tools parameter is not passed when no executor_context."""
result = get_llm_response(
llm=mock_llm,
messages=[{"role": "user", "content": "test"}],
@@ -202,13 +202,14 @@ class TestGetLlmResponse:
mock_llm.call.assert_called_once()
call_kwargs = mock_llm.call.call_args[1]
assert "tools" in call_kwargs
assert call_kwargs["tools"] is None
# tools should NOT be in kwargs when there are no tools
# This maintains backward compatibility with code that checks "tools" in kwargs
assert "tools" not in call_kwargs
def test_passes_none_tools_when_context_has_no_tools(
def test_does_not_pass_tools_when_context_has_no_tools(
self, mock_llm, mock_printer
):
"""Test that tools=None is passed when context has no tools."""
"""Test that tools parameter is not passed when context has no tools."""
mock_context = Mock()
mock_context.tools = []
mock_context.messages = [{"role": "user", "content": "test"}]
@@ -233,8 +234,9 @@ class TestGetLlmResponse:
mock_llm.call.assert_called_once()
call_kwargs = mock_llm.call.call_args[1]
assert "tools" in call_kwargs
assert call_kwargs["tools"] is None
# tools should NOT be in kwargs when there are no tools
# This maintains backward compatibility with code that checks "tools" in kwargs
assert "tools" not in call_kwargs
class TestAgetLlmResponse:
@@ -293,8 +295,8 @@ class TestAgetLlmResponse:
assert call_kwargs["tools"][0]["name"] == "async_test_tool"
@pytest.mark.asyncio
async def test_passes_none_tools_when_no_context(self, mock_llm, mock_printer):
"""Test that tools=None is passed when no executor_context."""
async def test_does_not_pass_tools_when_no_context(self, mock_llm, mock_printer):
"""Test that tools parameter is not passed when no executor_context."""
result = await aget_llm_response(
llm=mock_llm,
messages=[{"role": "user", "content": "test"}],
@@ -305,8 +307,9 @@ class TestAgetLlmResponse:
mock_llm.acall.assert_called_once()
call_kwargs = mock_llm.acall.call_args[1]
assert "tools" in call_kwargs
assert call_kwargs["tools"] is None
# tools should NOT be in kwargs when there are no tools
# This maintains backward compatibility with code that checks "tools" in kwargs
assert "tools" not in call_kwargs
class TestToolsPassedToGeminiModels: