Repository navigation
Python: Support async conditions in switch-case edge groups - #9669
Hardik K (hardikkaurani) wants to merge 2 commits into
Conversation
…t#9642) - Allow async predicates in Case and SwitchCaseEdgeGroupCase by typing condition as EdgeCondition - Support awaitable selection results in FanOutEdgeRunner.send_message - Add support for async condition evaluation in SwitchCaseEdgeGroup selection_func - Add comprehensive unit tests in test_edge.py and workflow integration tests in test_workflow.py
|
Hi Jose Alvarez (@jpalvarezl), I've opened this PR to resolve issue #9642 ("Support async conditions in switch-case edge groups"). Summary of Changes:
Whenever you have a moment, please feel free to review. Thank you! |
Bicheng (Kenneth) (BichengWang)
left a comment
There was a problem hiding this comment.
Reviewed 4935175c1796688b7e60786caea2c9576571550e offline on macOS / Python 3.13.16. The edge, workflow, and serialization suites pass: 145 tests. Restoring the three implementation files to merge base c01db29b761196665f7f9eafcd1ec9b6c1d196ef makes five of the six added regression tests fail; the matching-first-case control still passes.
Eight additional workflow probes pass at this head: true/false results from futures and custom awaitables, cancellation without evaluating the next case, an error in a later async predicate, rejection of invalid async fan-out selections, and a synchronous match skipping the later async predicate. Changed-file Ruff lint and formatting checks also pass.
I found no blocking code issue in the diff. This is focused verification; I did not run the full workspace suite, type checkers, distribution builds, or live providers. Issue #9642 currently has no maintainer agreement comment or ready-for-implementation label, so the contribution approval prerequisite still needs maintainer confirmation.
|
Hi Bicheng (Kenneth) (@BichengWang), Thank you for the thorough review and for running the extensive offline verification probes across Python 3.13! In response to your feedback, I have codified those exact probe scenarios into the automated test suite in commit 8021fb5 (
Validation Summary:
Regarding the issue prerequisite: issue #9642 is currently assigned to Eduard van Valkenburg (@eavanvalkenburg). Pinging Eduard van Valkenburg (@eavanvalkenburg) and Jose Alvarez (@jpalvarezl) for maintainer confirmation and review whenever convenient. Thank you! |
Motivation & Context
In
agent-framework(Python), standard edge conditions support asynchronous predicates viaEdgeCondition: TypeAlias = Callable[[Any], bool | Awaitable[bool]], andEdge.should_routeawaits the condition when it returns an awaitable.However, switch-case edge groups (
CaseandSwitchCaseEdgeGroupCase) were restricted to synchronous predicates (Callable[[Any], bool]). In practice, when an asynchronous predicate was passed toCase, callingcase.condition(message)produced a coroutine object. Because coroutine objects are truthy in Python, the first case would always immediately match regardless of input, leaving an unawaited coroutine and emittingRuntimeWarning: coroutine '...' was never awaited. Furthermore,FanOutEdgeRunner.send_messageinvokedself._selection_func(...)synchronously without awaiting awaitable selection results.Routing in workflows frequently requires async operations (e.g. LLM classification, external API checks, or async database lookups). This PR enables async conditions in switch-case edge groups while maintaining full backward compatibility with synchronous conditions.
Description & Review Guide
What are the major changes?
Case.conditionandSwitchCaseEdgeGroupCase.conditiontyping fromCallable[[Any], bool]toEdgeCondition(Callable[[Any], bool | Awaitable[bool]]).FanOutEdgeGroup._selection_funcandselection_funcproperty to acceptCallable[[Any, list[str]], list[str] | Awaitable[list[str]]] | None.SwitchCaseEdgeGroup.__init__'s internalselection_functo evaluate cases sequentially: if a condition returns an awaitable, it seamlessly evaluates and awaits the result (and subsequent cases if necessary) before returning the target executor ID.FanOutEdgeRunner.send_messageto check ifselection_resultsis awaitable (inspect.isawaitable(...)) and await it accordingly.packages/core/tests/workflow/test_edge.pycovering async condition matching, async fallthrough to default, condition evaluation ordering with mixed sync/async predicates, async condition error propagation, and async fan-out selectors.packages/core/tests/workflow/test_workflow.pyverifying end-to-end switch-case routing with async conditions.What is the impact of these changes?
async def) or callables returningAwaitable[bool]toCase(condition=...)without errors or warnings.What do you want reviewers to focus on?
SwitchCaseEdgeGroup's selection function ensuring "first match wins" semantics are preserved whether conditions are sync or async.Related Issue
Fixes #9642
AI Assistance
AI assistance details: Implementation of async condition support in switch-case edge groups and runners, comprehensive unit & workflow tests, and PR description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) - a workflow keeps the label and title prefix in sync automatically.