mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-05 01:02:37 +00:00
fix: prevent result_as_answer from returning error as final answer
When a tool with result_as_answer=True raises an exception, the agent was receiving result_as_answer=True and returning the error string as the final answer. Now we set result_as_answer=False when an error event is emitted, allowing the agent to reflect and retry. Fixes crewAIInc/crewAI#5156 --------- Co-authored-by: NIK-TIGER-BILL <nik.tiger.bill@github.com> Co-authored-by: Greyson LaLonde <greyson.r.lalonde@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a058a3b15b
commit
bfbdba426f
@@ -1592,11 +1592,11 @@ def execute_single_native_tool_call(
|
||||
color="green",
|
||||
)
|
||||
|
||||
# Check result_as_answer
|
||||
is_result_as_answer = bool(
|
||||
original_tool
|
||||
and hasattr(original_tool, "result_as_answer")
|
||||
and original_tool.result_as_answer
|
||||
and not error_event_emitted
|
||||
)
|
||||
|
||||
return NativeToolCallResult(
|
||||
|
||||
@@ -17,6 +17,8 @@ from crewai.utilities.agent_utils import (
|
||||
_format_messages_for_summary,
|
||||
_split_messages_into_chunks,
|
||||
convert_tools_to_openai_schema,
|
||||
execute_single_native_tool_call,
|
||||
NativeToolCallResult,
|
||||
parse_tool_call_args,
|
||||
summarize_messages,
|
||||
)
|
||||
@@ -1033,3 +1035,46 @@ class TestParseToolCallArgs:
|
||||
_, error = parse_tool_call_args("{bad json}", "tool", "call_7")
|
||||
assert error is not None
|
||||
assert set(error.keys()) == {"call_id", "func_name", "result", "from_cache", "original_tool"}
|
||||
|
||||
|
||||
class TestExecuteSingleNativeToolCall:
|
||||
"""Tests for execute_single_native_tool_call."""
|
||||
|
||||
def test_result_as_answer_false_on_tool_error(self) -> None:
|
||||
"""When a tool with result_as_answer=True raises, result_as_answer must be False.
|
||||
|
||||
Regression test for https://github.com/crewAIInc/crewAI/issues/5156
|
||||
"""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
class FailingTool(BaseTool):
|
||||
name: str = "failing_tool"
|
||||
description: str = "A tool that always fails"
|
||||
result_as_answer: bool = True
|
||||
|
||||
def _run(self, **kwargs: Any) -> str:
|
||||
raise RuntimeError("intentional failure")
|
||||
|
||||
tool = FailingTool()
|
||||
tool_call = MagicMock()
|
||||
tool_call.id = "call_1"
|
||||
tool_call.function.name = "failing_tool"
|
||||
tool_call.function.arguments = "{}"
|
||||
|
||||
result = execute_single_native_tool_call(
|
||||
tool_call,
|
||||
available_functions={"failing_tool": tool._run},
|
||||
original_tools=[tool],
|
||||
structured_tools=None,
|
||||
tools_handler=None,
|
||||
agent=None,
|
||||
task=None,
|
||||
crew=None,
|
||||
event_source=MagicMock(),
|
||||
printer=None,
|
||||
verbose=False,
|
||||
)
|
||||
|
||||
assert isinstance(result, NativeToolCallResult)
|
||||
assert result.result_as_answer is False
|
||||
assert "Error executing tool" in result.result
|
||||
|
||||
Reference in New Issue
Block a user