Repository navigation
Conversation
Strix Security ReviewWarning This pull request has 78 commits after the last Strix review ( No security issues found. Review summaryReviewed PR #8054, which changes Updated for Reviewed by Strix |
StepExecutor._execute_native_tool_calls returned before appending the tool message when a result_as_answer tool ran, so an assistant message with tool_calls was left with dangling tool_call_ids and the outer loop called the LLM again on that malformed history. The result_as_answer result was discarded in favor of the next LLM answer and the remaining calls in the batch were never executed. Answer every declared tool call with a tool message, execute the whole batch, and end the step with the result_as_answer tool's result.
adf5756 to
00a0807
Compare
Related issue
None — found by code inspection of the plan-and-execute step executor; no existing issue covers this path. (Returning contributor — #7487 merged — so the first-time-contributor issue requirement does not apply.)
Summary
StepExecutor._execute_native_tool_callsreturned as soon as a tool markedresult_as_answerran — before appending the tool message for that call and before executing the rest of the batch. The assistant message carryingtool_callswas therefore left without anytoolreply (danglingtool_call_ids), and the_execute_nativemulti-turn loop kept going: the next LLM call saw a malformed history that OpenAI/Anthropic reject ("An assistant message with 'tool_calls' must be followed by tool messages responding to each tool_call_id"), and the tool's result was discarded in favor of the LLM's next text answer.The default executor handles the same situation by appending the tool message first and finishing with the tool's result (
AgentFinishonresult_as_answer,lib/crewai/src/crewai/agents/crew_agent_executor.py:1096-1104), matching the documented meaning of the flag: "Flag to check if the tool should be the final agent answer." (lib/crewai/src/crewai/tools/base_tool.py:180-183).Changes
_execute_native_tool_callsnow executes the whole batch, answers every declaredtool_call_idwith a tool message, and returns(results, final_answer), wherefinal_answeris the firstresult_as_answerresult in the batch (if any)._execute_nativereturnsfinal_answerimmediately, ending the multi-turn loop, so the step's result is the tool's result — mirroringCrewAgentExecutor'sAgentFinishbehavior._execute_native_tool_callswas updated for the new return shape.Verification
Both new regression tests fail on
mainand pass with this change. Commands run (uv workspace, macOS arm64, Python 3.13.15):uv run pytest lib/crewai/tests/agents/test_agent_executor.py -q -k "native_result_as_answer"2 failed— no tool messages appended (assert set() == {'call_answer', 'call_side'}) and the step result was the LLM's next answer (assert 'done' == 'answer_tool-result')2 passeduv run pytest lib/crewai/tests/agents/test_agent_executor.py -q→100 passed, 2 failed; the two failures (TestVisionImageFormatContract::test_anthropic_provider_has_image_block_converter,TestResponseFormatWithKickoff::test_kickoff_response_format_with_planning_and_tools) fail identically on unpatchedmain— pre-existing, unrelated to this change.uv run pytest lib/crewai/tests/tools/test_tool_failure.py -q→97 passeduv run pytest lib/crewai/tests/hooks/test_deny_reaches_the_caller.py -q→15 passeduv run pytest lib/crewai/tests/agents/ -q -k "result_as_answer"→5 passeduv run ruff check lib/→All checks passed!uv run ruff format --check lib/→942 files already formatteduv run mypy --config-file pyproject.toml lib/crewai/src/crewai/agents/step_executor.py→Success: no issues found in 1 source fileAdditional context
This pull request was prepared with AI coding assistance. Per
.github/CONTRIBUTING.mdit requires thellm-generatedlabel; external contributors cannot apply labels, so maintainers please apply it during triage (same as #7336).Note
Medium Risk
Changes plan-and-execute native tool batching and step termination; behavior is localized to StepExecutor but affects any planning step using result_as_answer with native function calling.
Overview
Fixes native plan-step execution when a tool is marked
result_as_answer.Previously
StepExecutor._execute_native_tool_callsexited on the first such tool before running the rest of the batch or appendingtoolmessages, leaving assistanttool_callswithout replies and letting_execute_nativecall the LLM again (often failing provider validation and returning the wrong step result). The batch now runs to completion, everytool_call_idgets a reply, and the method returns(concatenated_results, final_answer);_execute_nativestops the loop immediately whenfinal_answeris set so the step answer is the tool output, aligned with the default agent executor’sresult_as_answerbehavior.Regression tests cover multi-tool batches (stub LLM, message history, and
execute()end-to-end).Reviewed by Cursor Bugbot for commit 00a0807. Bugbot is set up for automated code reviews on this repo. Configure here.