Skip to content

fix(agent): implement ExecutorContext protocol on AgentExecutor for human_input support (#6347)#6372

Open
ThryLox wants to merge 3 commits into
crewAIInc:mainfrom
ThryLox:fix/agent-executor-human-input-context
Open

fix(agent): implement ExecutorContext protocol on AgentExecutor for human_input support (#6347)#6372
ThryLox wants to merge 3 commits into
crewAIInc:mainfrom
ThryLox:fix/agent-executor-human-input-context

Conversation

@ThryLox

@ThryLox ThryLox commented Jun 27, 2026

Copy link
Copy Markdown

Summary

Fixes #6347 by implementing the required ExecutorContext and AsyncExecutorContext protocol methods on AgentExecutor.

Root Cause

In crewAI 1.15.0, AgentExecutor became the default agent executor. However, when Task(human_input=True) or ask_for_human_input=True is enabled, the human input provider (SyncHumanInputProvider / AsyncHumanInputProvider) casts the executor to ExecutorContext / AsyncExecutorContext and calls _format_feedback_message, _invoke_loop, and _ainvoke_loop. Because AgentExecutor lacked implementations for these methods, execution crashed with an AttributeError.

Fix

Implemented _format_feedback_message, _invoke_loop, and _ainvoke_loop on AgentExecutor in lib/crewai/src/crewai/experimental/agent_executor.py and added a protocol contract regression test in test_agent_executor.py.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced human-in-the-loop feedback handling to format feedback and reliably continue execution in both synchronous and asynchronous runs.
    • When an agent run completes without a final result, the system now raises a clearer error.
    • Feedback is now prepared more consistently before being applied.
  • Tests
    • Added automated coverage to prevent regressions in the human-feedback execution protocol.

…uman_input support (crewAIInc#6347)

In crewAI 1.15.0, AgentExecutor became the default executor class. However, when Task(human_input=True) or ask_for_human_input=True is enabled, human feedback handlers cast AgentExecutor to ExecutorContext and invoke _format_feedback_message, _invoke_loop, and _ainvoke_loop. Because AgentExecutor lacked these methods, execution crashed with AttributeError. This commit implements all required ExecutorContext and AsyncExecutorContext protocol methods on AgentExecutor and adds a regression contract test.
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fea1f22d-07a4-46fe-a2ac-99237d47e982

📥 Commits

Reviewing files that changed from the base of the PR and between 6d9623e and ae54124.

📒 Files selected for processing (1)
  • lib/crewai/tests/agents/test_agent_executor.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai/tests/agents/test_agent_executor.py

📝 Walkthrough

Walkthrough

Adds _format_feedback_message, _invoke_loop, and _ainvoke_loop to AgentExecutor, and adds tests covering the human-input protocol and loop reset behavior.

Changes

Human Input Protocol Implementation

Layer / File(s) Summary
HITL helper methods on AgentExecutor
lib/crewai/src/crewai/experimental/agent_executor.py
_format_feedback_message formats feedback with the i18n template and format_message_for_llm. _invoke_loop and _ainvoke_loop reset execution state, rerun kickoff()/kickoff_async(), and return AgentFinish or raise RuntimeError.
Human-input protocol tests
lib/crewai/tests/agents/test_agent_executor.py
Tests assert the protocol methods exist and verify feedback formatting plus sync and async loop reset behavior.

Suggested Reviewers

  • greysonlalonde
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding ExecutorContext support for human_input on AgentExecutor.
Linked Issues check ✅ Passed The PR adds the missing AgentExecutor contract methods and regression tests for the default human-input flow.
Out of Scope Changes check ✅ Passed The changes stay focused on human-input executor support and related tests, with no obvious unrelated additions.
✨ 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.

@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: 2

🧹 Nitpick comments (1)
lib/crewai/tests/agents/test_agent_executor.py (1)

2399-2405: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

This regression test is too weak to protect the restored HITL flow.

hasattr only catches another missing-method regression. It will still pass if _invoke_loop() immediately re-hits max_iter or if planning-mode reruns ignore the appended feedback, so it does not cover the behavior this PR is restoring.

🤖 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/tests/agents/test_agent_executor.py` around lines 2399 - 2405, The
current regression test only checks that AgentExecutor still exposes helper
methods, so it won’t catch broken HITL behavior in the restored flow. Strengthen
test_agent_executor_implements_human_input_protocol in the AgentExecutor test
suite to assert the actual human-in-the-loop path: verify _invoke_loop and/or
_ainvoke_loop consume appended feedback, continue execution beyond max_iter when
feedback is provided, and preserve planning-mode rerun behavior. Use the
existing symbols _format_feedback_message, _invoke_loop, _ainvoke_loop, and
_is_training_mode to drive a behavior-based assertion rather than simple hasattr
checks.
🤖 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/experimental/agent_executor.py`:
- Around line 3199-3210: Planning-mode reruns are still losing the human
feedback because the `generate_plan()` / `StepExecutor.execute()` path only uses
task text and dependency results, not the appended feedback message from
`_format_feedback_message()`. Update the planning execution flow in
`AgentExecutor` so the rerun preserves and forwards the latest feedback from
`self.state.messages` (or the equivalent stored context) into plan generation
and step execution, ensuring planned agents see the same feedback that
non-planning runs receive.
- Around line 3212-3220: The _invoke_loop flow is re-entering with a stale
iteration counter, so `check_max_iterations()` can immediately force another
final answer before new feedback is used. Reset `state.iterations` to the
initial value before calling `kickoff()` in `_invoke_loop` (and the related
wrapper path in the same area) so the agent can make a fresh LLM call. Keep the
existing finish validation after `kickoff()` and preserve the `AgentFinish`
check.

---

Nitpick comments:
In `@lib/crewai/tests/agents/test_agent_executor.py`:
- Around line 2399-2405: The current regression test only checks that
AgentExecutor still exposes helper methods, so it won’t catch broken HITL
behavior in the restored flow. Strengthen
test_agent_executor_implements_human_input_protocol in the AgentExecutor test
suite to assert the actual human-in-the-loop path: verify _invoke_loop and/or
_ainvoke_loop consume appended feedback, continue execution beyond max_iter when
feedback is provided, and preserve planning-mode rerun behavior. Use the
existing symbols _format_feedback_message, _invoke_loop, _ainvoke_loop, and
_is_training_mode to drive a behavior-based assertion rather than simple hasattr
checks.
🪄 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: ab3fdd0f-a3c2-47b6-b12c-deca91e285ee

📥 Commits

Reviewing files that changed from the base of the PR and between 6491f5a and a322cff.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/experimental/agent_executor.py
  • lib/crewai/tests/agents/test_agent_executor.py

Comment on lines +3199 to +3210
def _format_feedback_message(self, feedback: str) -> LLMMessage:
"""Format feedback as a message for the LLM.

Args:
feedback: User feedback string.

Returns:
Formatted message dict.
"""
return format_message_for_llm(
I18N_DEFAULT.slice("feedback_instructions").format(feedback=feedback)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Planning-mode reruns still drop the human feedback.

The provider appends _format_feedback_message(feedback) to context.messages, but a planning-enabled rerun goes through generate_plan() and StepExecutor.execute() using task text/dependency results only. Nothing on that path reads self.state.messages, so planned agents can satisfy the protocol surface while ignoring the feedback entirely.

Also applies to: 3212-3230

🤖 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/experimental/agent_executor.py` around lines 3199 -
3210, Planning-mode reruns are still losing the human feedback because the
`generate_plan()` / `StepExecutor.execute()` path only uses task text and
dependency results, not the appended feedback message from
`_format_feedback_message()`. Update the planning execution flow in
`AgentExecutor` so the rerun preserves and forwards the latest feedback from
`self.state.messages` (or the equivalent stored context) into plan generation
and step execution, ensuring planned agents see the same feedback that
non-planning runs receive.

Comment thread lib/crewai/src/crewai/experimental/agent_executor.py

@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.

🧹 Nitpick comments (2)
lib/crewai/tests/agents/test_agent_executor.py (2)

2417-2421: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the reset happens before kickoff().

This only proves iterations == 0 after _invoke_loop() returns. Because current_answer is pre-seeded and kickoff() is a no-op, an implementation that resets after kickoff() would still pass. Capture executor.state.iterations inside a kickoff side effect and set current_answer there so the test validates the intended ordering.

🤖 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/tests/agents/test_agent_executor.py` around lines 2417 - 2421, The
_invoke_loop() test currently only checks executor.state.iterations after the
method finishes, so it can miss the reset ordering relative to kickoff(). Update
the test around AgentExecutor._invoke_loop by using a kickoff side effect on the
patched kickoff method to capture executor.state.iterations at call time and
assign current_answer there, so the assertion verifies iterations is reset
before kickoff() runs rather than afterward.

2399-2405: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a behavioral test for _ainvoke_loop, not just hasattr.

The async half of the contract is still effectively untested here. Since the PR restores AsyncExecutorContext, mirror the reset-and-rerun assertion for _ainvoke_loop() so an async regression does not slip past on a simple method-presence check.

🤖 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/tests/agents/test_agent_executor.py` around lines 2399 - 2405, The
current test only checks that AgentExecutor exposes _ainvoke_loop, but it does
not verify the async behavior. Update
test_agent_executor_implements_human_input_protocol to mirror the existing
reset-and-rerun pattern for _invoke_loop by actually exercising
AgentExecutor._ainvoke_loop() and asserting the expected rerun/reset behavior,
so the async contract is covered rather than just method presence.
🤖 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.

Nitpick comments:
In `@lib/crewai/tests/agents/test_agent_executor.py`:
- Around line 2417-2421: The _invoke_loop() test currently only checks
executor.state.iterations after the method finishes, so it can miss the reset
ordering relative to kickoff(). Update the test around
AgentExecutor._invoke_loop by using a kickoff side effect on the patched kickoff
method to capture executor.state.iterations at call time and assign
current_answer there, so the assertion verifies iterations is reset before
kickoff() runs rather than afterward.
- Around line 2399-2405: The current test only checks that AgentExecutor exposes
_ainvoke_loop, but it does not verify the async behavior. Update
test_agent_executor_implements_human_input_protocol to mirror the existing
reset-and-rerun pattern for _invoke_loop by actually exercising
AgentExecutor._ainvoke_loop() and asserting the expected rerun/reset behavior,
so the async contract is covered rather than just method presence.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 500f6c10-1efc-4bb4-bb7c-522627fb158f

📥 Commits

Reviewing files that changed from the base of the PR and between a322cff and 6d9623e.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/experimental/agent_executor.py
  • lib/crewai/tests/agents/test_agent_executor.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai/src/crewai/experimental/agent_executor.py

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] Task(human_input=True) crashes with AttributeError after default executor swap from CrewAgentExecutor to AgentExecutor in 1.15.0

1 participant