From 1b06e11da0cd9add848e7a999113ee9aa3b178a0 Mon Sep 17 00:00:00 2001 From: Diwak4r Date: Sun, 26 Jul 2026 13:40:44 +0545 Subject: [PATCH] fix(reasoning): use regex for plan readiness detection instead of exact string match The readiness check was matching only the exact phrase 'READY: I am ready to execute the task.' but the refine plan prompt instructs the model to conclude with just 'READY' or 'NOT READY'. Models responding with standalone 'READY' were falsely detected as NOT READY. Replace the three rigid substring checks with a case- insensitive regex that matches standalone READY while excluding NOT READY via negative lookbehind. Closes #6204 --- .../src/crewai/utilities/reasoning_handler.py | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/crewai/src/crewai/utilities/reasoning_handler.py b/lib/crewai/src/crewai/utilities/reasoning_handler.py index 21c0a1e1d5..a3ef4594c3 100644 --- a/lib/crewai/src/crewai/utilities/reasoning_handler.py +++ b/lib/crewai/src/crewai/utilities/reasoning_handler.py @@ -4,6 +4,7 @@ import json import logging +import re from typing import TYPE_CHECKING, Any, Final, Literal, cast from pydantic import BaseModel, Field @@ -411,7 +412,7 @@ def _create_reasoning_plan( return ( response_str, [], - "READY: I am ready to execute the task." in response_str, + AgentReasoning._is_plan_ready(response_str), ) except HookAborted: @@ -437,7 +438,7 @@ def _create_reasoning_plan( return ( fallback_str, [], - "READY: I am ready to execute the task." in fallback_str, + AgentReasoning._is_plan_ready(fallback_str), ) except HookAborted: raise @@ -585,6 +586,21 @@ def _create_refine_prompt(self, current_plan: str) -> str: current_plan=current_plan, ) + @staticmethod + def _is_plan_ready(response: str) -> bool: + """Check if the agent indicated readiness in the planning response. + + Detects standalone ``READY`` that is not part of ``NOT READY``. + Case-insensitive to handle ``Ready``, ``READY``, ``ready``, etc. + + Args: + response: The LLM response text. + + Returns: + True if the agent declared READY, False otherwise. + """ + return bool(re.search(r"(? tuple[str, bool]: """Parses the planning response to extract the plan and readiness. @@ -599,7 +615,7 @@ def _parse_planning_response(response: str) -> tuple[str, bool]: return "No plan was generated.", False plan = response - ready = "READY: I am ready to execute the task." in response + ready = AgentReasoning._is_plan_ready(response) return plan, ready