Skip to content

fix: improve READY detection in reasoning handler#6218

Open
PHclaw wants to merge 1 commit into
crewAIInc:mainfrom
PHclaw:fix/reasoning-ready-detection
Open

fix: improve READY detection in reasoning handler#6218
PHclaw wants to merge 1 commit into
crewAIInc:mainfrom
PHclaw:fix/reasoning-ready-detection

Conversation

@PHclaw

@PHclaw PHclaw commented Jun 18, 2026

Copy link
Copy Markdown

Summary

Fixes #6204

The reasoning handler only recognized the exact string "READY: I am ready to execute the task." when checking if an agent is ready to execute. This caused the handler to always detect "NOT READY" even when the model clearly outputs just "READY".

Problem

When using reasoning with models like Ollama GLM5.2, the model outputs "READY" after the plan content (e.g., <PLAN CONTENTS>\n---\nREADY), but the handler fails to detect it because it only matches the full sentence "READY: I am ready to execute the task.".

This affects 3 code paths:

  1. _call_with_function fallback when JSON parsing fails
  2. _call_with_function fallback when function calling throws an exception
  3. _parse_planning_response (the text-based parsing path)

Solution

Replace the exact string match with a regex-based check that:

  • Matches READY as a standalone keyword
  • Excludes NOT READY (negative lookbehind for NOT )
  • Handles various LLM output formats (bare READY, ---\nREADY, full sentence, etc.)
def _is_ready_response(text: str) -> bool:
    return bool(re.search(r"(?<!\bNOT\s)READY\b", text))

Testing

  • re.search(r"(?<!\bNOT\s)READY\b", "READY") → True ✓
  • re.search(r"(?<!\bNOT\s)READY\b", "---\nREADY") → True ✓
  • re.search(r"(?<!\bNOT\s)READY\b", "READY: I am ready to execute the task.") → True ✓
  • re.search(r"(?<!\bNOT\s)READY\b", "NOT READY") → False ✓
  • re.search(r"(?<!\bNOT\s)READY\b", "You indicated you weren't ready.") → False ✓

Summary by CodeRabbit

  • Bug Fixes
    • Refined readiness detection in the agent planning workflow to more reliably identify agent readiness states across different response formats.

The reasoning handler only recognized the exact string
'READY: I am ready to execute the task.' which caused it to
always detect 'NOT READY' even when the model outputs just 'READY'.

Now uses regex to match 'READY' as a standalone keyword while
excluding 'NOT READY', handling various LLM output formats.

Fixes crewAIInc#6204
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new module-level helper _is_ready_response(text: str) -> bool is added to reasoning_handler.py, using a regex match for READY while excluding NOT READY variants. Three hardcoded substring checks across the planning flow are replaced with calls to this helper.

Changes

Readiness Detection Refactor

Layer / File(s) Summary
_is_ready_response helper definition
lib/crewai/src/crewai/utilities/reasoning_handler.py
Adds _is_ready_response(text: str) -> bool at module level (lines 107–121), using a regex pattern to match READY while explicitly excluding NOT READY variants, with docstring examples of accepted and rejected inputs.
Readiness check call sites updated
lib/crewai/src/crewai/utilities/reasoning_handler.py
Replaces the hardcoded "READY: I am ready to execute the task." in ... substring checks at the JSON/function-calling parse site (line 427), the function-calling fallback path (line 451), and inside _parse_planning_response (line 611) with calls to _is_ready_response(...).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: improving READY detection in the reasoning handler by replacing strict string matching with flexible regex-based detection.
Linked Issues check ✅ Passed The PR directly addresses issue #6204 by implementing regex-based READY detection that handles flexible LLM output formats, replacing the rigid exact-string matching that caused false NOT READY results.
Out of Scope Changes check ✅ Passed All changes are focused on improving READY detection in the reasoning handler as required by issue #6204, with no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/crewai/src/crewai/utilities/reasoning_handler.py`:
- Around line 109-120: The regex pattern in the _is_ready_response function
needs to be fixed to handle both word boundary issues and variable whitespace.
Replace the current regex r"(?<!NOT\s)READY" with a two-pass check approach:
first verify that "NOT READY" does not appear in the text (case-insensitive),
then check for "READY" as a standalone word using proper word boundaries like
r"\bREADY\b". This avoids false positives from matching READY inside words like
ALREADY or UNREADY, and handles any amount of whitespace between NOT and READY
without relying on fixed-width lookbehinds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1a57a5e-00d4-4bb8-93bd-e2da989c285d

📥 Commits

Reviewing files that changed from the base of the PR and between c0fa66d and 59879fc.

📒 Files selected for processing (1)
  • lib/crewai/src/crewai/utilities/reasoning_handler.py

Comment on lines +109 to +120
def _is_ready_response(text: str) -> bool:
"""Check if the LLM response indicates readiness to execute.

Matches 'READY' as a standalone keyword while excluding 'NOT READY'.
This handles various LLM output formats:
- "READY"
- "---\nREADY"
- "READY: I am ready to execute the task."
But NOT:
- "NOT READY"
"""
return bool(re.search(r"(?<!NOT\s)READY", text))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Regex pattern has false-positive risks that contradict the docstring.

Two issues with r"(?<!NOT\s)READY":

  1. No word boundary after READY — will match READY inside words like "ALREADY" or "UNREADY", which are plausible in plan text (e.g., "I have ALREADY identified the tools").

  2. Fixed-width lookbehind can't handle variable whitespace — Python's re module requires fixed-width lookbehinds, so "NOT READY" (double space) bypasses the check since the 4 chars before READY are "T ", not "NOT ".

Since downstream code gates task execution on plan.ready (see AgentExecutor which only creates todos when plan_ready is true), false positives would cause premature execution.

🛠️ Proposed fix using two-pass check for robustness
 def _is_ready_response(text: str) -> bool:
     """Check if the LLM response indicates readiness to execute.

     Matches 'READY' as a standalone keyword while excluding 'NOT READY'.
     This handles various LLM output formats:
     - "READY"
     - "---\nREADY"
     - "READY: I am ready to execute the task."
     But NOT:
     - "NOT READY"
+    - "NOT  READY" (variable whitespace)
+    - "ALREADY" (READY within other words)
     """
-    return bool(re.search(r"(?<!NOT\s)READY", text))
+    has_ready = bool(re.search(r"\bREADY\b", text))
+    has_not_ready = bool(re.search(r"\bNOT\s+READY\b", text, re.IGNORECASE))
+    return has_ready and not has_not_ready
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/src/crewai/utilities/reasoning_handler.py` around lines 109 - 120,
The regex pattern in the _is_ready_response function needs to be fixed to handle
both word boundary issues and variable whitespace. Replace the current regex
r"(?<!NOT\s)READY" with a two-pass check approach: first verify that "NOT READY"
does not appear in the text (case-insensitive), then check for "READY" as a
standalone word using proper word boundaries like r"\bREADY\b". This avoids
false positives from matching READY inside words like ALREADY or UNREADY, and
handles any amount of whitespace between NOT and READY without relying on
fixed-width lookbehinds.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Reasoning plan always detects "NOT READY" even though the model indicates "READY"

1 participant