Skip to content

[INC-285] Inner workflows#2230

Merged
PawelPeczek-Roboflow merged 43 commits intomainfrom
INC-285/inner-workflows
Apr 17, 2026
Merged

[INC-285] Inner workflows#2230
PawelPeczek-Roboflow merged 43 commits intomainfrom
INC-285/inner-workflows

Conversation

@dkosowski87
Copy link
Copy Markdown
Contributor

@dkosowski87 dkosowski87 commented Apr 14, 2026

What does this PR do?

Linked issue: INC-285

  • New workflow block roboflow_core/inner_workflow@v1 allowing to nest a previously saved workflow by providing it's workflow_id, workspace_id and version
  • Added reference resolution using get_workflow_specification to fetch the inner workflows recursively and normalize them to a full workflow definition
  • Added validations for inner workflow graph nesting level, total inner workflows, parameter bindings
  • Added an inlining solution that inlines the steps in the inner workflows into the main workflow.

Testing

  • I have tested this change locally
  • I have added/updated tests for this change

Test details:

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code where necessary, particularly in hard-to-understand areas
  • My changes generate no new warnings or errors
  • I have updated the documentation accordingly (if applicable)

Additional Context

- Introduced UseSubworkflowBlockV1 to enable execution of embedded workflows with parameter mapping from the parent workflow.
- Updated loader.py to include the new block in the workflow loading process.
- Added constants for the new block type in constants.py.
- Updated ExecutionEngineV1 to initialize LocalSubworkflowRunner if not already provided in init_parameters.
- Enhanced LocalSubworkflowRunner to execute nested workflows using the v1 workflow executor.
- Improved documentation for subworkflow components to clarify usage and implementation details.
- Introduced new functions for compiling and validating nested workflows within the execution engine.
- Added `GraphCompilationResult` class to encapsulate compilation results.
- Enhanced `compile_workflow` to handle nested workflows and their parameters.
- Created `compiler_bridge.py` for subworkflow composition validation and output projection.
- Updated existing workflow compilation logic to integrate subworkflow handling.
- Introduced new functions for executing `use_subworkflow` steps, including `run_use_subworkflow_simd` and `run_use_subworkflow_non_simd`.
- Added utility functions to determine if a step is a subworkflow and to manage runtime parameters.
- Enhanced the main execution engine to support error handling for subworkflow steps.
- Created a new file for subworkflow step execution logic, improving modularity and maintainability.
- Introduced end-to-end tests for the `use_subworkflow` functionality, validating parameter mapping between parent and child workflows.
- Implemented tests for both single-level and multi-level nested workflows to ensure correct execution and output.
- Enhanced test coverage for the execution engine's handling of subworkflows, contributing to improved reliability and maintainability of the workflow system.
- Introduced `nested_output_dimensionality_lift` to `BlockManifest` for tracking output dimensionality from child steps in embedded workflows.
- Updated `denote_data_flow_for_step` to incorporate the new lift value when determining output dimensionality offsets.
- Implemented `max_projection_output_lift_from_embedded_workflow` to calculate the maximum lift from child steps.
- Enhanced the `LocalSubworkflowRunner` and related execution functions to utilize the new dimensionality handling.
- Added utility functions for reshaping results based on the nested output dimensionality lift during execution.
- Expanded integration tests to validate the new functionality and ensure correct behavior in nested workflows.
- Added support for resolving `use_subworkflow` steps that reference saved workflows by ID into inline `embedded_workflow` definitions.
- Introduced a new module for reference resolution, including a default resolver for fetching workflow specifications.
- Updated the compilation process to normalize references before parsing and validation, ensuring mutual exclusivity between embedded workflows and reference fields.
- Expanded integration and unit tests to cover new reference resolution features, validating correct behavior in various scenarios.
…onality

- Renamed `use_subworkflow` to `use_inner_workflow` throughout the codebase for consistency.
- Introduced a new document detailing the design and goals of inner workflow composition.
- Updated compilation and execution logic to support inner workflows, including validation of composition and nesting depth.
- Enhanced error handling for inner workflow composition issues, including cycle detection and nesting depth limits.
- Added new modules for inner workflow management, including reference resolution and execution strategies.
- Updated environment variables to reflect the new inner workflow terminology, ensuring backward compatibility with legacy subworkflow settings.
- Removed legacy references to `workflows_core.subworkflow_spec_resolver` in favor of the updated `workflows_core.inner_workflow_spec_resolver`.
- Enhanced documentation for the `use_subworkflow` functionality, clarifying the usage of inline definitions and workspace configurations.
- Streamlined error messages related to workflow resolution, ensuring clarity in user feedback.
- Renamed `use_subworkflow` to `inner_workflow` throughout the codebase for consistency and clarity.
- Introduced a new `InnerWorkflowBlockV1` class to handle execution of nested workflows with parameter mapping.
- Updated documentation to reflect changes in terminology and provide clear guidelines on inner workflow composition.
- Enhanced compilation and execution logic to support inner workflows, including validation of parameter bindings and nesting depth.
- Improved error handling for inner workflow references and added integration tests to validate functionality.
- Updated documentation to clarify the `max_nesting_depth` environment variable, removing references to the legacy `WORKFLOWS_MAX_SUBWORKFLOW_DEPTH`.
- Streamlined the execution engine to exclusively utilize `workflows_core.inner_workflow_runner`, eliminating fallback to the legacy runner.
- Enhanced the inner workflow step execution logic by removing deprecated references and ensuring consistency in the handling of nested workflows.
- Improved code clarity and maintainability by consolidating inner workflow runner logic.
- Introduced a new integration test file for `roboflow_core/inner_workflow@v1`, validating nested workflow execution.
- Implemented tests to ensure correct parameter mapping and output resolution between parent and child workflows.
- Enhanced documentation to include the new test file in the inner workflow design overview.
- Renamed `embedded_workflow` references to `workflow` throughout the codebase for consistency and clarity.
- Updated documentation to reflect changes in parameter names and improve clarity on workflow execution.
- Enhanced validation logic to ensure correct handling of workflow references and inline definitions.
- Adjusted integration and unit tests to align with the new terminology and validate functionality of inner workflows.
…tion`

- Renamed all instances of `workflow` to `workflow_definition` across the codebase for consistency and clarity.
- Adjusted validation logic and error messages to reflect the new terminology.
- Updated integration and unit tests to ensure proper functionality with the new parameter name.
- Enhanced documentation to clarify the changes in parameter handling for inner workflows.
- Updated variable names from `embedded` to `inner` for clarity and consistency in the inner workflow test cases.
- Ensured that all references to workflow definitions in the tests align with the updated terminology.
- Improved readability of the test code by standardizing naming conventions across multiple test functions.
- Introduced multiple test cases to validate the equivalence between nested inner workflows and their inlined counterparts.
- Implemented tests for various scenarios, including parameter passing, output resolution, and handling of batch inputs.
- Ensured consistency in behavior between inner workflows and inlined steps, enhancing the robustness of the integration testing framework.
- Updated common helper functions to support the new test cases and improve code reusability.
- Deleted the test file `test_workflow_with_inner_workflow.py`, which contained end-to-end tests for nested workflow execution.
- This removal is part of a cleanup effort to streamline the testing framework and eliminate redundant or outdated test cases.
- Future tests will focus on more relevant scenarios and improve overall test coverage.
- Deleted the `inner_workflow_design.md` file, which outlined the design and goals for nested workflows.
- This removal is part of a broader effort to streamline documentation and focus on more relevant and updated resources.
- Future documentation will prioritize clarity and conciseness in conveying workflow functionality.
- Deleted the section on inner workflow composition from the `workflows_compiler.md` file to streamline documentation.
- This change aligns with recent efforts to focus on more relevant and updated resources regarding workflow functionality.
Comment thread mkdocs.yml Outdated
- Workflow Execution: workflows/workflow_execution.md
- Kinds: workflows/kinds/
- Compiler: workflows/workflows_compiler.md
- Inner workflow design: workflows/inner_workflow_design.md
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks like this file is not commited

Largest positive ``get_output_dimensionality_offset()`` among child steps referenced
by the child workflow's JsonField outputs (e.g. ``dynamic_crop`` -> 1).
"""
from inference.core.workflows.execution_engine.v1.compiler.entities import StepNode
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

is there an issue with global imports here? I guess circular dependencies, right?


lift = 0
graph = child_graph.execution_graph
for jf in child_graph.parsed_workflow_definition.outputs:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

voting for more descriptive var names

For each ``inner_workflow`` step, compile the child workflow (for cache + output kinds)
and attach resolved_child_outputs on the manifest copy.
"""
from inference.core.workflows.execution_engine.v1.compiler.entities import (
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if symbol ParsedWorkflowDefinition is present at the signature level - why internal imports?

"""Errors raised by inner-workflow composition validation."""


class InnerWorkflowCompositionError(Exception):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

maybe some generic workflow-related error could be on top of error hierarchy here

context="workflow_execution | inner_workflow",
)
if len(raw) != 1:
raise ExecutionEngineRuntimeError(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

isnt that assumption error? I mean the safeguard for limitations / assumptions rather that "something wrong which happened in runtime"?

)
inner = echo_child_workflow()

with mock.patch.object(ModelManager, "add_model"), mock.patch.object(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

cool 👍

nested_engine = execution_engine(
model_manager,
_nested_by_ref_workflow(),
extra_init_parameters={WORKFLOWS_CORE_INNER_WORKFLOW_SPEC_RESOLVER: resolver},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

clever

dkosowski87 and others added 13 commits April 17, 2026 01:11
- Updated multiple integration tests to replace instances of `first_non_empty_or_default` with `scalar_only_echo`, ensuring uniformity in the workflow steps.
- Adjusted test documentation to reflect the changes in step types and their expected behavior.
- This refactor enhances the clarity and maintainability of the test suite for inner workflows.
…rst non-empty

- Deleted the test file `test_inner_workflow_continue_if_last_in_inner_with_parent_first_non_empty.py`, which validated the behavior of the inner workflow when using `continue_if` with a parent workflow's `first_non_empty_or_default` step.
- This removal is part of ongoing efforts to streamline the testing framework and eliminate outdated or redundant test cases.
- Updated integration tests to change references from `first_non_empty` to `echo` in both the workflow definitions and output selectors.
- This change enhances consistency across the test cases and aligns with recent refactoring efforts to standardize step types in inner workflows.
- Introduced a new test case to validate the behavior of the inner workflow when the parent runs detection and applies dynamic cropping on the inner model's predictions.
- Added a new function `child_detection_only_for_parent_dynamic_crop` to define the inner workflow structure for this scenario.
- This enhancement improves the integration testing framework by ensuring the correctness of nested workflows involving detection and cropping operations.
- Updated the inner workflow implementation to validate parameter bindings and inline child workflows at compile time, enhancing performance and simplifying execution.
- Removed the `InnerWorkflowRunner` and related execution logic, as inner workflows are now expanded into ordinary steps during compilation.
- Adjusted documentation and comments to reflect the new inlining behavior and updated parameter binding requirements.
- Added tests to validate the new parameter binding rules for child workflows, ensuring robustness in the compilation process.
- Refactored the test suite to introduce a new mock function for object detection inference, improving the handling of single and batch image requests.
- Added a new test case to validate the behavior of the inner workflow when processing a list of images, ensuring consistent results with the single-image case.
- Updated assertions to verify the correct number of calls and parameters in the mock, enhancing the robustness of the integration tests for nested workflows.
- Introduced two new test cases to validate the behavior of the inner workflow when using `continue_if` with the outer workflow's `echo` step.
- Enhanced the `_inner_continue_if_only_outer_echo_name_matches_parent` and `_nested_workflow_continue_if_inner_echo_outer` functions to support the new test scenarios.
- Updated assertions to ensure the correctness of the integration tests, verifying that the nested and flat workflow results match as expected.
…etections

- Introduced a new test case to validate the behavior of the inner workflow when applying dimension collapse on object detection results from the inner model.
- Implemented mock functions to simulate object detection responses and ensure consistent results when processing single and batch images.
- Enhanced assertions to verify that the nested and flat workflow results match, confirming the correctness of the integration tests for dimension collapse functionality.
- Introduced a new inner workflow function `child_dimension_collapse_from_parent_detections` to handle dimension collapse using predictions from the parent workflow.
- Added a comprehensive integration test to validate the behavior of the inner workflow when applying dimension collapse on object detection results.
- Implemented mock functions to simulate object detection responses and ensure consistent results for both single and batch image processing.
- Enhanced assertions to confirm that the results from the nested and flat workflows match, ensuring the correctness of the integration tests for dimension collapse functionality.
- Updated the inner workflow validation logic to improve error handling for invalid step entries and parameter bindings.
- Introduced new error classes for better granularity in error reporting, including `InnerWorkflowInvalidStepEntryError` and `InnerWorkflowParameterBindingsError`.
- Refactored the `validate_inner_workflow_composition_from_raw_workflow_definition` function to enhance clarity and maintainability.
- Adjusted the maximum nesting depth configuration for inner workflows and updated related validation checks.
- Added unit tests to ensure robust validation of inner workflow definitions and parameter bindings.
- Added detailed docstrings to several functions in the inline workflow module, improving clarity on their purpose, parameters, and error handling.
- Updated function descriptions to include information about exceptions raised, enhancing the usability and maintainability of the code.
- This change aims to provide better guidance for developers working with inner workflows and facilitate easier debugging and integration.
- Introduced new unit tests for the `inline_inner_workflow_steps` function, focusing on its behavior with minimal workflow graphs.
- Added comprehensive test cases to validate the handling of inner workflow steps, ensuring correct inlining and reference resolution.
- Enhanced the test suite for the inner workflow module to improve coverage and maintainability, facilitating easier debugging and integration in future developments.
- This addition aims to strengthen the testing framework for inner workflows and ensure robust functionality across various scenarios.

def _workflow_identity_fingerprint(raw_workflow_definition: Dict[str, Any]) -> str:
"""Stable opaque id for composition graph nodes."""
payload = json.dumps(raw_workflow_definition, sort_keys=True, separators=(",", ":")).encode(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this is just to leave comment and check later

I worry that some workflow definition may carry base64 images - at least I remember (maybe phantom memory) some iteration of UI doing so - this way, we will run excessive computation in some cases for the things not directly being meaningful part of workflow definition

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, written a note to myself

- Updated the `_contains_inner_workflow_step` function to return `False` for invalid input types instead of raising exceptions, improving usability and error handling.
- Modified corresponding unit tests to reflect the new behavior, ensuring that non-list and non-dict entries are correctly handled without exceptions.
- This change enhances the robustness of the inner workflow validation process and simplifies error management for users.
- Reformatted several code sections across multiple files to enhance readability, including consistent line breaks and indentation.
- Updated the `validate_workflow_or_reference` method to improve clarity in the inline workflow validation process.
- Refactored function calls to maintain a consistent style, ensuring better maintainability and understanding of the codebase.
- These changes aim to streamline the inner workflow implementation and facilitate easier future modifications.
- Introduced a new environment variable `WORKFLOWS_MAX_INNER_WORKFLOW_COUNT` to set the maximum allowed inner workflow steps.
- Added `InnerWorkflowTotalCountError` to handle cases where the inner workflow step count exceeds the defined limit.
- Updated the `validate_inner_workflow_composition` function to include validation for the total count of inner workflow steps.
- Enhanced unit tests to cover scenarios for total count validation, ensuring robust error handling and compliance with the new limits.
- These changes improve the overall validation logic for inner workflows, enhancing usability and error management.
@PawelPeczek-Roboflow
Copy link
Copy Markdown
Collaborator

ok, one more thing - bump of EE version and mention in changelog

- Introduced the `roboflow_core/inner_workflow@v1` block, allowing workflows to embed other workflows inline.
- Updated the execution engine to version `1.9.0`, incorporating compile-time inlining of nested workflows.
- Added a new documentation page detailing inner workflows, including usage, parameter bindings, and compile-time validation.
- Enhanced the workflows compiler to handle inner workflow steps, ensuring proper validation and inlining during compilation.
- Updated existing documentation to reference the new inner workflow design and its capabilities.
@PawelPeczek-Roboflow PawelPeczek-Roboflow merged commit 38b0fbf into main Apr 17, 2026
46 checks passed
@PawelPeczek-Roboflow PawelPeczek-Roboflow deleted the INC-285/inner-workflows branch April 17, 2026 17:51
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.

2 participants