Skip to content

fix: result_as_answer should not apply to tool errors#5170

Open
r266-tech wants to merge 3 commits into
crewAIInc:mainfrom
r266-tech:fix/result-as-answer-on-error
Open

fix: result_as_answer should not apply to tool errors#5170
r266-tech wants to merge 3 commits into
crewAIInc:mainfrom
r266-tech:fix/result-as-answer-on-error

Conversation

@r266-tech
Copy link
Copy Markdown

@r266-tech r266-tech commented Mar 30, 2026

Closes #5156

Problem

When a tool with result_as_answer=True encounters an error, the error message is unconditionally returned as the agent's final answer. This prevents the agent from reflecting on the error and potentially retrying.

For example, a code execution tool with result_as_answer=True that raises SyntaxError would produce:

Error executing tool: SyntaxError('invalid syntax')

as the final agent output — instead of letting the agent see the error and try to fix it.

Root Cause

_append_tool_result_and_check_finality() checks result_as_answer=True unconditionally:

if (
    original_tool
    and hasattr(original_tool, "result_as_answer")
    and original_tool.result_as_answer
):
    return AgentFinish(...)  # Always returns, even on error

There is no distinction between successful tool outputs and error results.

Fix

Track an is_error flag through _execute_single_native_tool_call() and check it before returning AgentFinish.

Error paths (is_error=True):

  • JSON parse failure in tool arguments
  • Tool not found
  • Hook blocked execution
  • Max usage limit reached
  • Exception during tool execution

Success paths (is_error=False):

  • Cached result available
  • Tool executed successfully

The check becomes:

if (
    not is_error
    and original_tool
    and hasattr(original_tool, "result_as_answer")
    and original_tool.result_as_answer
):
    return AgentFinish(...)

When is_error=True, the method returns None, allowing the agent loop to continue and let the LLM reflect on the error.

1 file changed, +10/-1


Note

Medium Risk
Changes the native tool-calling finalize logic so error outputs no longer short-circuit the agent loop; this can alter when agents stop vs. retry/reflect, impacting behavior for tools relying on result_as_answer. Logic is localized but affects core execution flow for tool calls.

Overview
Prevents tools with result_as_answer=True from returning error outputs as the agent’s final answer during native tool calling.

The executor now propagates an is_error flag from _execute_single_native_tool_call() (covering parse failures, missing tools, hook blocks, usage-limit blocks, and exceptions) and adds a heuristic _looks_like_tool_error() check, so _append_tool_result_and_check_finality() only returns AgentFinish for successful tool results.

Written by Cursor Bugbot for commit c273dff. This will update automatically on new commits. Configure here.

When a tool with result_as_answer=True encounters an error (exception,
hook block, max usage limit, or tool-not-found), the error message was
being returned as the final agent answer. This prevents the agent from
reflecting on the error and retrying.

Fix: track is_error flag through _execute_single_native_tool_call and
check it in _append_tool_result_and_check_finality before returning
AgentFinish. Only successful tool outputs should become the final answer
when result_as_answer=True.

Closes crewAIInc#5156
Comment thread lib/crewai/src/crewai/agents/crew_agent_executor.py
Copy link
Copy Markdown
Author

@r266-tech r266-tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Added is_error = True to the hook_blocked and max_usage_reached branches to handle the cache-hit-then-blocked edge case.

…es cached result

Addresses Bugbot review: when a cache hit sets is_error=False but the
tool is subsequently blocked by a hook or usage limit, the result is
overwritten with an error message but is_error was not updated. This
caused result_as_answer to incorrectly return error strings as final answers.
@Vamshi3130
Copy link
Copy Markdown

what if tool returns string of error instead of raise an exception as shown in documentation and i belive currently being followed in all builtin tools

Address review feedback: many built-in crewAI tools return error strings
like "Error performing search: ..." instead of raising exceptions. Add
_looks_like_tool_error() heuristic to detect these, complementing the
is_error flag which handles exception/parse failures.

Patterns detected:
- "Error ..." (most built-in tools: brave_search, rag, aws/s3, ocr)
- "I encountered an error ..." (tool_usage.py i18n messages)
@r266-tech
Copy link
Copy Markdown
Author

Good catch! Many built-in tools (brave_search, rag, aws/s3, ocr) return error strings like "Error performing search: ..." without raising exceptions. I've added a _looks_like_tool_error() static method as a fallback:

  • Detects "Error ..." prefix (most built-in tools)
  • Detects "I encountered an error ..." (tool_usage.py i18n messages)

So now both cases are covered: (1) is_error flag for exception/parse failures, (2) string-based detection for tools that return error strings.

The PR has been updated with the additional commit.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

original_tool
not is_error
and not self._looks_like_tool_error(result)
and original_tool
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error prefix misclassifies valid tool outputs

Medium Severity

The new result_as_answer guard treats any successful result starting with Error or I encountered an error as a failure via _looks_like_tool_error. Legitimate outputs with those prefixes are now prevented from finalizing in crew_agent_executor.py, changing behavior for valid result_as_answer tools.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants