Skip to content

Build FlowDefinition from Flow DSL metadata#6017

Merged
vinibrsl merged 2 commits into
mainfrom
flow-structure-from-dsl
Jun 3, 2026
Merged

Build FlowDefinition from Flow DSL metadata#6017
vinibrsl merged 2 commits into
mainfrom
flow-structure-from-dsl

Conversation

@vinibrsl
Copy link
Copy Markdown
Member

@vinibrsl vinibrsl commented Jun 2, 2026

Introduce FlowDefinition, a serializable model built from the Flow DSL's runtime metadata. It becomes the structural contract for Flow methods, triggers, routers, state, and configuration.

The visualization layer is the first consumer: flow_structure and build_flow_structure now project from the definition instead of re-introspecting the class. The runner still executes from live registries, but the definition gives future runners a single static contract to read.

This replaces AST source parsing for router return values, crew references, and state schema with runtime metadata plus explicit @router(paths=...) or Literal/Enum return hints. AST parsing was fragile and could silently fail for dynamic or non-inspectable methods.

The refactor removes obsolete introspection and serializer code:

  • Delete flow_serializer.py, flow/utils.py, and visualization/schema.py
  • Move flow structure modeling into flow_definition.py
  • Simplify visualization building around the static definition contract

Note

Medium Risk
Large refactor of flow structure, visualization, and router metadata with deleted public shims; runtime behavior should stay registry-based but static graphs may differ when router emits are not declared or inferrable.

Overview
Adds a serializable FlowDefinition contract (methods, triggers, state, config, diagnostics, JSON/YAML export) and moves Python class → definition projection into dsl via build_flow_definition, with decorators recording FlowMethodDefinition fragments at decoration time.

Flow.flow_definition() is built lazily on first access; runtime still uses live registries but _router_paths becomes _router_emit. @router gains optional emit=, with Literal/Enum return hints when omitted, replacing AST parsing for static router outputs.

Visualization now projects from FlowDefinition only (no method source/signatures/OpenAPI); UI terminology shifts from router paths to router events. Removes flow_serializer, flow/utils, visualization/schema, and the public flow_structure export; human_feedback / persist align metadata (__router_emit__, _human_feedback_llm, persistence stamping) with the new contract.

Reviewed by Cursor Bugbot for commit c9e171d. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Flow.flow_definition() with JSON/YAML export, schema, validation diagnostics, and a serializable FlowDefinition contract.
  • Improvements

    • Visualization builds from FlowDefinition; UI/highlighting now use “Router Events” instead of “Router Paths”.
    • Routers accept explicit emit values and infer emits from return types when omitted.
    • Persistence and human-feedback decorators preserve live LLM references for resume.
  • Refactor

    • Repository reorganized around DSL, FlowDefinition contract, and runtime execution.
  • Chores

    • Removed legacy flow-structure inspection and related OpenAPI helpers/tests.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR replaces runtime/AST-based flow introspection with a serializable FlowDefinition contract (Pydantic), adds router emit handling/inference in decorators, preserves persistence and human-feedback LLM metadata under new attributes, makes runtime lazily cache FlowDefinition, updates visualization and UI to router-events, and adds/updates tests for the contract-driven flow model.

Changes

Flow definition contract refactor

Layer / File(s) Summary
DSL decorators: condition helpers and router emit parameter
lib/crewai/src/crewai/flow/dsl.py
Core decorators (start, listen, router, and_, or_) refactored with shared trigger/condition validation, annotation unwrapping, and router emit inference from Literal/Enum return types. router adds a keyword-only emit parameter and normalizes/ deduplicates events.
FlowDefinition Pydantic contract with serialization
lib/crewai/src/crewai/flow/flow_definition.py
New FlowDefinition and related Pydantic models for methods/state/config/persistence/human-feedback plus diagnostics. Adds to_dict/to_json/to_yaml/from_*, json_schema, validate_contract (non-fatal diagnostics), and diagnostic merging/logging.
Wrapper and persistence metadata capture
lib/crewai/src/crewai/flow/flow_wrappers.py, lib/crewai/src/crewai/flow/human_feedback.py, lib/crewai/src/crewai/flow/persistence/decorators.py
Wrappers now preserve __router_emit__, __flow_persistence_config__, __flow_method_definition__; human-feedback stores live LLM as _human_feedback_llm; persistence stamping centralizes metadata via _stamp_persistence_metadata and _PRESERVED_FLOW_ATTRS.
Flow runtime lazy definition building and caching
lib/crewai/src/crewai/flow/runtime.py
Flow gains _flow_definition cache and flow_definition() classmethod to lazily build/cache FlowDefinition; FlowMeta collects router_emit; resume and condition evaluation updated to use new attributes and string checks.
Definition-driven visualization with router event metadata
lib/crewai/src/crewai/flow/visualization/builder.py, lib/crewai/src/crewai/flow/visualization/types.py, lib/crewai/src/crewai/flow/visualization/renderers/interactive.py, lib/crewai/src/crewai/flow/visualization/assets/interactive.js
build_flow_structure accepts FlowDefinition or Flow and derives nodes/edges from definition conditions. NodeMetadata uses router_events, StructureEdge uses is_router_event/router_event. Renderers and interactive JS updated with new highlighter APIs (highlightAllRouterEvents, highlightRouterEvent).
Flow definition contract validation test suite
lib/crewai/tests/test_flow_definition.py
Comprehensive tests for exports, DSL-agnosticness, DSL→FlowDefinition mapping, emit inference (Literal/Enum/Union/Annotated), diagnostics preservation and logging, persistence/human-feedback serialization, and cache isolation.
Test updates for router events and LLM naming
lib/crewai/tests/test_flow_visualization.py, lib/crewai/tests/test_async_human_feedback.py, lib/crewai/tests/test_flow.py, lib/crewai/tests/test_human_feedback_decorator.py, lib/crewai/tests/test_human_feedback_integration.py
Visualization tests now attach FlowDefinition contracts and assert router_events/is_router_event; human-feedback tests use _human_feedback_llm and updated test names; flow tests updated to use event labels.
Module cleanup and export consolidation
lib/crewai/src/crewai/flow/__init__.py, lib/crewai/src/crewai/flow/flow.py, lib/crewai/src/crewai/flow/utils.py, lib/crewai/src/crewai/flow/types.py, lib/crewai/src/crewai/flow/persistence/__init__.py
Removed flow_serializer.py and visualization schema module; removed flow_structure re-export and several small type aliases; modules now declare explicit __all__ lists and narrower exports.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • crewAIInc/crewAI#5997: Both PRs heavily refactor Flow DSL and definition/runtime separation, especially around router trigger inference (paths vs emit) and exports in dsl.py, flow_definition.py, and related utilities.

Suggested labels

enhancement

Suggested reviewers

  • greysonlalonde

Poem

🐰 I stitched the flow into a contract neat,
Events replaced the paths beneath our feet,
Decorators hum and LLMs tuck in tight,
Visuals draw from definitions in light—
A rabbit hops and whispers: "Refactor right."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.66% 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
Title check ✅ Passed The title clearly summarizes the main change: introducing FlowDefinition construction from Flow DSL metadata, which is the central objective of this large refactoring.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch flow-structure-from-dsl

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.

Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/crewai/src/crewai/flow/human_feedback.py (1)

633-640: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep router metadata when wrapping an existing router.

This wrapper still drops __is_router__ and __router_paths__. If someone stacks @human_feedback around @router(...) without emit=..., the resulting method stops being recognized as a router by both FlowMeta and build_flow_definition().

Suggested fix
         for attr in [
             "__is_start_method__",
             "__trigger_methods__",
             "__condition_type__",
             "__trigger_condition__",
             "__is_flow_method__",
+            "__is_router__",
+            "__router_paths__",
             "__flow_persistence_config__",
         ]:
             if hasattr(func, attr):
                 setattr(wrapper, attr, getattr(func, attr))
🤖 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/flow/human_feedback.py` around lines 633 - 640, The
wrapper currently strips router metadata when wrapping an existing router;
update the attribute-preservation loop in the human_feedback wrapper to also
copy "__is_router__" and "__router_paths__" (in addition to the existing
attributes like "__is_flow_method__") from the original function to the wrapped
function so that FlowMeta and build_flow_definition() still recognize methods
wrapped with `@router`(... ) then `@human_feedback`; ensure the code checks for
hasattr(orig, attr) and sets the same attribute on the wrapper for both
"__is_router__" and "__router_paths__".
🤖 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/flow/dsl.py`:
- Around line 298-302: Explicit router paths assigned to
wrapper.__router_paths__ are copied verbatim, causing duplicates; change the
assignment so explicit paths are normalized and deduplicated the same way
inferred paths are (convert each path to str and preserve order while removing
duplicates, e.g., by using an order-preserving unique operation such as
dict.fromkeys or equivalent) so that both the single-string branch and the
iterable branch produce a deduplicated list of string paths.

In `@lib/crewai/src/crewai/flow/flow_definition.py`:
- Around line 147-153: from_dict currently replaces any diagnostics present in
the serialized input with fresh validation results; preserve any serialized
diagnostics instead of overwriting them by reading diagnostics from the input
(e.g., get diagnostics from data before calling model_validate), deserialize or
convert them into the same Diagnostic type used by FlowDefinition, run
validate_contract() to produce new diagnostics, merge the two diagnostic
lists/sets (avoid duplicates) into definition.diagnostics, and then call
definition.log_diagnostics(); update FlowDefinition.from_dict to use
model_validate, preserve/deserialize input diagnostics, merge with
validate_contract() output, and assign the merged collection to
definition.diagnostics.

In `@lib/crewai/src/crewai/flow/persistence/decorators.py`:
- Around line 69-78: The allowlist _PRESERVED_FLOW_ATTRS in decorators.py is
missing the "_hf_llm" attribute so methods wrapped by `@human_feedback` lose the
live LLM handle when also wrapped by `@persist`; update the tuple
_PRESERVED_FLOW_ATTRS to include the string "_hf_llm" so the `@persist` wrapper
preserves the live LLM handle (refer to the _PRESERVED_FLOW_ATTRS constant and
the `@human_feedback/`@persist decorator logic to validate behavior).

In `@lib/crewai/src/crewai/flow/visualization/analysis.py`:
- Around line 82-89: The current router-path matching uses _condition_atoms()
which treats composite listeners (e.g., {"and": [...]}) as matches and thus
misaligns with builder._extract_direct_or_triggers() and build_flow_structure();
replace uses of _condition_atoms() with _direct_or_triggers() when checking if a
path belongs to a child in the loop that iterates _router_paths(method)
(affecting the block that populates parent_children for router_name and the
similar block around lines 220-230), so that only direct-OR triggers are
considered when appending child_name to parent_children[router_name], keeping
levels, ancestors, and outgoing-edge counts consistent with the builder
semantics.
- Around line 162-169: The DFS stops when a node is first visited so ancestors
discovered later through another parent never propagate; update
_build_ancestor_dict/_dfs_ancestors to use an iterative worklist or change
propagation approach: compute initial ancestor sets (each node includes its
direct parents), then repeatedly process nodes (or children) and merge parent
ancestor sets into a child, re-enqueue child when its ancestor set grows until
no changes remain; ensure _dfs_ancestors no longer short-circuits on a simple
visited flag but instead triggers downstream propagation when an ancestor set is
expanded so merged graph shapes like A->B->D->E and A->C->D correctly add C into
ancestors["E"].

---

Outside diff comments:
In `@lib/crewai/src/crewai/flow/human_feedback.py`:
- Around line 633-640: The wrapper currently strips router metadata when
wrapping an existing router; update the attribute-preservation loop in the
human_feedback wrapper to also copy "__is_router__" and "__router_paths__" (in
addition to the existing attributes like "__is_flow_method__") from the original
function to the wrapped function so that FlowMeta and build_flow_definition()
still recognize methods wrapped with `@router`(... ) then `@human_feedback`; ensure
the code checks for hasattr(orig, attr) and sets the same attribute on the
wrapper for both "__is_router__" and "__router_paths__".
🪄 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: ab9eca7c-fe53-40f2-b7a6-c4744694598b

📥 Commits

Reviewing files that changed from the base of the PR and between c81b4fe and e6d877e.

📒 Files selected for processing (16)
  • lib/crewai/src/crewai/flow/__init__.py
  • lib/crewai/src/crewai/flow/dsl.py
  • lib/crewai/src/crewai/flow/flow_definition.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
  • lib/crewai/src/crewai/flow/flow_wrappers.py
  • lib/crewai/src/crewai/flow/human_feedback.py
  • lib/crewai/src/crewai/flow/persistence/decorators.py
  • lib/crewai/src/crewai/flow/runtime.py
  • lib/crewai/src/crewai/flow/utils.py
  • lib/crewai/src/crewai/flow/visualization/analysis.py
  • lib/crewai/src/crewai/flow/visualization/builder.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/src/crewai/flow/visualization/types.py
  • lib/crewai/tests/test_flow_definition_contract.py
  • lib/crewai/tests/test_flow_serializer.py
  • lib/crewai/tests/test_flow_visualization.py
💤 Files with no reviewable changes (4)
  • lib/crewai/src/crewai/flow/utils.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/tests/test_flow_serializer.py

Comment thread lib/crewai/src/crewai/flow/dsl.py Outdated
Comment thread lib/crewai/src/crewai/flow/flow_definition.py
Comment thread lib/crewai/src/crewai/flow/persistence/decorators.py
Comment thread lib/crewai/src/crewai/flow/visualization/analysis.py Outdated
Comment thread lib/crewai/src/crewai/flow/visualization/analysis.py Outdated
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch from e6d877e to 29d7911 Compare June 2, 2026 20:52
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
Comment thread lib/crewai/tests/test_flow_definition_contract.py Fixed
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch 2 times, most recently from bf6354c to 60d5d48 Compare June 2, 2026 21:37
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch 3 times, most recently from d6bf045 to 424806c Compare June 3, 2026 15:10
Comment thread lib/crewai/tests/test_flow_definition.py Fixed
Comment thread lib/crewai/tests/test_flow_definition.py Fixed
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch 2 times, most recently from e3fa660 to 7c96d06 Compare June 3, 2026 15:52
@vinibrsl vinibrsl changed the title Build a static FlowDefinition from the Flow DSL Build FlowDefinition from Flow DSL metadata Jun 3, 2026
@vinibrsl vinibrsl marked this pull request as ready for review June 3, 2026 15:53
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch from 7c96d06 to 0213cb6 Compare June 3, 2026 15:53
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
lib/crewai/src/crewai/flow/visualization/types.py (1)

22-29: ⚡ Quick win

Tighten StructureEdge typing: make is_router_event required (router_event stays optional).

edge["is_router_event"] is read unconditionally in calculate_execution_paths() and the interactive renderer, and every StructureEdge(...) creation in lib/crewai/src/crewai/flow/visualization/builder.py stamps is_router_event (False for non-router edges, True for router edges). So there’s no runtime KeyError risk from total=False.

The type contract can be improved for static checking by making is_router_event a required TypedDict key (e.g., using typing_extensions.Required[bool]) while keeping router_event optional, since non-router edges don’t set it and the renderer guards with "router_event" in edge.

🤖 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/flow/visualization/types.py` around lines 22 - 29,
StructureEdge should require is_router_event while keeping router_event
optional: update the TypedDict definition (StructureEdge) to mark
is_router_event as a required bool using typing_extensions.Required[bool] and
keep router_event as Optional[str] (or absent) so static checkers know
is_router_event always exists; add the necessary import from typing_extensions
and adjust the type on StructureEdge in
lib/crewai/src/crewai/flow/visualization/types.py so callers like
calculate_execution_paths and the interactive renderer (and the builder that
constructs edges) satisfy the stronger contract.
🤖 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/flow/dsl.py`:
- Around line 790-800: The FlowHumanFeedbackDefinition currently embeds
human_feedback.metadata verbatim which can include non-serializable objects;
update the constructor call that builds FlowHumanFeedbackDefinition (in the
function/method around FlowHumanFeedbackDefinition creation) to serialize
metadata using _serialize_static_value just like llm and provider do — i.e.,
replace the direct metadata=getattr(config, "metadata", None) with
metadata=_serialize_static_value(getattr(config, "metadata", None), diagnostics,
f"{path}.metadata") so metadata is normalized for the contract.
- Around line 216-227: The helper _string_values_from_annotation currently
recurses into every generic argument, so annotations like list[Literal["a"]] or
dict[str, Literal["b"]] incorrectly contribute to FlowMethodDefinition.emit;
change _string_values_from_annotation to only recurse when the annotation origin
is a union-like wrapper or Annotated (e.g., origins matching typing.Union / "|"
or where getattr(origin,"__name__","") == "Annotated"), and stop recursion for
other container origins (list, dict, Sequence, Mapping, etc.); update
_get_router_return_events (which calls _string_values_from_annotation) to rely
on the tightened behavior so emit is derived only from
Union/Optional/Annotated-wrapped Literals and not from arbitrary containers.

In `@lib/crewai/src/crewai/flow/flow_definition.py`:
- Around line 167-179: The validation in validate_contract currently treats only
start is None as "no start", so a method with {"router": true, "start": false}
slips through; update validate_contract to use the FlowMethodDefinition.is_start
semantic (or otherwise treat falsy start the same as None) when checking for a
trigger: for each method in self.methods, if method.router is true and not
method.is_start() and method.listen is None then append the same
FlowDefinitionDiagnostic (code "router_without_trigger"); this ensures start:
false is considered "no start" like FlowMethodDefinition.is_start defines.

In `@lib/crewai/src/crewai/flow/visualization/assets/interactive.js`:
- Around line 1663-1672: The router-event chips currently reuse the generic
drawer-code-link click path which calls highlightTriggeredBy(eventName) and
stops after the first matching outgoing dashed edge; change the chip behavior so
each chip triggers an event-aware highlighter instead of highlightTriggeredBy:
create or call a handler like highlightRouterEvent(eventName) (or similar) that
finds and highlights all edges/listeners tied to that router_event (e.g.,
collect all graph edges/nodes whose metadata or data attributes reference the
given router_event and apply the highlight to each), and wire the chip click to
that handler via the .drawer-code-link for uniqueRouterEvents; alternatively, if
you prefer not to implement a new highlighter, make the per-event chips
non-clickable and preserve the existing title-level “highlight all” action.

---

Nitpick comments:
In `@lib/crewai/src/crewai/flow/visualization/types.py`:
- Around line 22-29: StructureEdge should require is_router_event while keeping
router_event optional: update the TypedDict definition (StructureEdge) to mark
is_router_event as a required bool using typing_extensions.Required[bool] and
keep router_event as Optional[str] (or absent) so static checkers know
is_router_event always exists; add the necessary import from typing_extensions
and adjust the type on StructureEdge in
lib/crewai/src/crewai/flow/visualization/types.py so callers like
calculate_execution_paths and the interactive renderer (and the builder that
constructs edges) satisfy the stronger contract.
🪄 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: 1aefe16d-0302-4936-b6d1-160e81f26335

📥 Commits

Reviewing files that changed from the base of the PR and between e6d877e and 0213cb6.

📒 Files selected for processing (24)
  • lib/crewai/src/crewai/flow/__init__.py
  • lib/crewai/src/crewai/flow/dsl.py
  • lib/crewai/src/crewai/flow/flow.py
  • lib/crewai/src/crewai/flow/flow_definition.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
  • lib/crewai/src/crewai/flow/flow_wrappers.py
  • lib/crewai/src/crewai/flow/human_feedback.py
  • lib/crewai/src/crewai/flow/persistence/__init__.py
  • lib/crewai/src/crewai/flow/persistence/decorators.py
  • lib/crewai/src/crewai/flow/runtime.py
  • lib/crewai/src/crewai/flow/types.py
  • lib/crewai/src/crewai/flow/utils.py
  • lib/crewai/src/crewai/flow/visualization/assets/interactive.js
  • lib/crewai/src/crewai/flow/visualization/builder.py
  • lib/crewai/src/crewai/flow/visualization/renderers/interactive.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/src/crewai/flow/visualization/types.py
  • lib/crewai/tests/test_async_human_feedback.py
  • lib/crewai/tests/test_flow.py
  • lib/crewai/tests/test_flow_definition.py
  • lib/crewai/tests/test_flow_serializer.py
  • lib/crewai/tests/test_flow_visualization.py
  • lib/crewai/tests/test_human_feedback_decorator.py
  • lib/crewai/tests/test_human_feedback_integration.py
💤 Files with no reviewable changes (7)
  • lib/crewai/src/crewai/flow/persistence/init.py
  • lib/crewai/tests/test_flow_serializer.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/src/crewai/flow/utils.py
  • lib/crewai/src/crewai/flow/init.py
  • lib/crewai/src/crewai/flow/types.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
✅ Files skipped from review due to trivial changes (1)
  • lib/crewai/src/crewai/flow/flow.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai/src/crewai/flow/visualization/builder.py

Comment thread lib/crewai/src/crewai/flow/dsl.py
Comment thread lib/crewai/src/crewai/flow/dsl.py
Comment thread lib/crewai/src/crewai/flow/flow_definition.py
Comment thread lib/crewai/src/crewai/flow/visualization/assets/interactive.js Outdated
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch from 0213cb6 to 513468d Compare June 3, 2026 17:19
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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/tests/test_flow_definition.py`:
- Around line 441-457: Change the brittle caplog assertion to only consider
records from the specific logger under test: filter caplog.records by
record.name (or record.logger.name) == "crewai.flow.flow_definition" and assert
that filtered list is empty (e.g., records = [r for r in caplog.records if
r.name == "crewai.flow.flow_definition"]; assert records == []). Apply the same
change in test_dynamic_router_does_not_log_at_class_definition_time (both
occurrences) so the tests only assert against the intended logger and ignore
unrelated warnings.
🪄 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: f1c6303f-cc67-4791-91e7-ec1e23e87e9d

📥 Commits

Reviewing files that changed from the base of the PR and between 0213cb6 and 513468d.

📒 Files selected for processing (24)
  • lib/crewai/src/crewai/flow/__init__.py
  • lib/crewai/src/crewai/flow/dsl.py
  • lib/crewai/src/crewai/flow/flow.py
  • lib/crewai/src/crewai/flow/flow_definition.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
  • lib/crewai/src/crewai/flow/flow_wrappers.py
  • lib/crewai/src/crewai/flow/human_feedback.py
  • lib/crewai/src/crewai/flow/persistence/__init__.py
  • lib/crewai/src/crewai/flow/persistence/decorators.py
  • lib/crewai/src/crewai/flow/runtime.py
  • lib/crewai/src/crewai/flow/types.py
  • lib/crewai/src/crewai/flow/utils.py
  • lib/crewai/src/crewai/flow/visualization/assets/interactive.js
  • lib/crewai/src/crewai/flow/visualization/builder.py
  • lib/crewai/src/crewai/flow/visualization/renderers/interactive.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/src/crewai/flow/visualization/types.py
  • lib/crewai/tests/test_async_human_feedback.py
  • lib/crewai/tests/test_flow.py
  • lib/crewai/tests/test_flow_definition.py
  • lib/crewai/tests/test_flow_serializer.py
  • lib/crewai/tests/test_flow_visualization.py
  • lib/crewai/tests/test_human_feedback_decorator.py
  • lib/crewai/tests/test_human_feedback_integration.py
💤 Files with no reviewable changes (7)
  • lib/crewai/src/crewai/flow/types.py
  • lib/crewai/src/crewai/flow/persistence/init.py
  • lib/crewai/src/crewai/flow/init.py
  • lib/crewai/tests/test_flow_serializer.py
  • lib/crewai/src/crewai/flow/flow_serializer.py
  • lib/crewai/src/crewai/flow/visualization/schema.py
  • lib/crewai/src/crewai/flow/utils.py
✅ Files skipped from review due to trivial changes (1)
  • lib/crewai/src/crewai/flow/flow.py
🚧 Files skipped from review as they are similar to previous changes (15)
  • lib/crewai/src/crewai/flow/visualization/types.py
  • lib/crewai/tests/test_human_feedback_decorator.py
  • lib/crewai/src/crewai/flow/visualization/renderers/interactive.py
  • lib/crewai/src/crewai/flow/flow_wrappers.py
  • lib/crewai/tests/test_human_feedback_integration.py
  • lib/crewai/src/crewai/flow/runtime.py
  • lib/crewai/src/crewai/flow/visualization/assets/interactive.js
  • lib/crewai/tests/test_flow.py
  • lib/crewai/src/crewai/flow/visualization/builder.py
  • lib/crewai/src/crewai/flow/human_feedback.py
  • lib/crewai/src/crewai/flow/persistence/decorators.py
  • lib/crewai/src/crewai/flow/dsl.py
  • lib/crewai/tests/test_async_human_feedback.py
  • lib/crewai/src/crewai/flow/flow_definition.py
  • lib/crewai/tests/test_flow_visualization.py

Comment thread lib/crewai/tests/test_flow_definition.py Outdated
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch 2 times, most recently from 7f8e756 to a82fae9 Compare June 3, 2026 17:51
Comment thread lib/crewai/src/crewai/flow/visualization/assets/interactive.js
Comment thread lib/crewai/src/crewai/flow/visualization/builder.py
Comment thread lib/crewai/src/crewai/flow/__init__.py
Comment thread lib/crewai/src/crewai/flow/dsl.py
Comment thread lib/crewai/src/crewai/flow/dsl.py
Comment thread lib/crewai/src/crewai/flow/flow_definition.py
Comment thread lib/crewai/src/crewai/flow/flow_wrappers.py
Comment thread lib/crewai/src/crewai/flow/flow_wrappers.py
Comment thread lib/crewai/src/crewai/flow/human_feedback.py
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch from a82fae9 to 667d26b Compare June 3, 2026 19:08
vinibrsl added 2 commits June 3, 2026 17:57
Introduce `FlowDefinition`, a serializable model built from the Flow
DSL's runtime metadata. It becomes the structural contract for Flow
methods, triggers, routers, state, and configuration.

The visualization layer is the first consumer: `flow_structure` and
`build_flow_structure` now project from the definition instead of
re-introspecting the class. The runner still executes from live
registries, but the definition gives future runners a single static
contract to read.

This replaces AST source parsing for router return values, crew
references, and state schema with runtime metadata plus explicit
`@router(paths=...)` or `Literal`/`Enum` return hints. AST parsing was
fragile and could silently fail for dynamic or non-inspectable methods.

The refactor removes obsolete introspection and serializer code:

* Delete `flow_serializer.py`, `flow/utils.py`, and
  `visualization/schema.py`
* Move flow structure modeling into `flow_definition.py`
* Simplify visualization building around the static definition contract
@vinibrsl vinibrsl force-pushed the flow-structure-from-dsl branch from 0b50ea9 to c9e171d Compare June 3, 2026 20:57
@vinibrsl vinibrsl merged commit 051fa0c into main Jun 3, 2026
54 of 55 checks passed
@vinibrsl vinibrsl deleted the flow-structure-from-dsl branch June 3, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants