Skip to content

Conversation

@m-k8s
Copy link

@m-k8s m-k8s commented Jan 4, 2026

Summary

Fix incorrect router path detection when combining @listen and @human_feedback(emit=...) decorators.

Problem

When a listener method is decorated with both @listen and @human_feedback with emit, the Flow metaclass incorrectly detects router paths by parsing the method's source code instead of using the __router_paths__ attribute set by @human_feedback.

Example:

@listen("begin")
@human_feedback(
    message="Review this:",
    emit=["approved", "rejected"],
    llm="gpt-4o-mini",
)
def review(self):
    return "content to review"

Before fix: _router_paths["review"] = ["content to review"] (wrong - parsed from return statement)

After fix: _router_paths["review"] = ["approved", "rejected"] (correct - from emit parameter)

This bug could also cause IndentationError when parsing source code of multi-decorated methods, because inspect.getsource() includes decorators with class-level indentation which can confuse ast.parse().

Root Cause

In FlowMeta.__new__, the code for listener methods that are also routers directly calls get_possible_return_constants() without first checking the __router_paths__ attribute:

# Before (buggy)
if hasattr(attr_value, "__is_router__") and attr_value.__is_router__:
    routers.add(attr_name)
    possible_returns = get_possible_return_constants(attr_value)  # Parses source!
    ...

However, the code for start methods that are routers correctly checks __router_paths__ first:

# Existing code for start methods (correct)
if hasattr(attr_value, "__router_paths__") and attr_value.__router_paths__:
    router_paths[attr_name] = attr_value.__router_paths__
else:
    possible_returns = get_possible_return_constants(attr_value)
    ...

Solution

Apply the same pattern to listener methods: check __router_paths__ first before falling back to source parsing.

Files Changed

  • lib/crewai/src/crewai/flow/flow.py - Fix router path detection for listeners
  • lib/crewai/tests/test_human_feedback_decorator.py - Add regression tests

Tests

Added TestListenerRouterPathDetection class with 2 tests:

  • test_listener_with_human_feedback_emit_has_router_paths - Basic case
  • test_multiple_listener_routers_detected - Multiple listener-routers in same flow

Test results:

  • Without fix: 2 FAILED
  • With fix: 2 PASSED

Related Documentation

This is a documented use case per docs/en/learn/human-feedback-in-flows.mdx:

Combining with Other Decorators

The @human_feedback decorator works with other flow decorators. Place it as the innermost decorator (closest to the function):

@listen(other_method)
@human_feedback(message="Review this too:")
def my_listener(self, data):
    return f"processed: {data}"

Note

Ensures correct router path detection for listener methods decorated with @human_feedback(emit=...), avoiding brittle source parsing and potential IndentationError.

  • In flow.py (FlowMeta.__new__), when a listener is also a router, first use __router_paths__ from the decorator; fall back to get_possible_return_constants only if absent
  • Adds TestListenerRouterPathDetection in test_human_feedback_decorator.py with cases for single and multiple listener-routers

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

m-k8s and others added 2 commits January 5, 2026 00:32
When a listener method is also a router (e.g., decorated with both
@listen and @human_feedback with emit), the router path detection
was directly calling get_possible_return_constants() which parses
the method's source code via AST.

This caused incorrect router paths (parsing return values instead of
emit values) and could cause IndentationError when the method had
multiple decorators, because inspect.getsource() includes decorators
with class-level indentation.

The fix aligns listener router handling with start method router
handling: check the __router_paths__ attribute first (set by
@human_feedback when emit is specified) before falling back to
source code parsing.

This is a documented use case per human-feedback-in-flows.mdx:
"The @human_feedback decorator works with other flow decorators."
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.

1 participant