Skip to content

add existing sub-workflow inside workflow#201

Open
rootflo-hardik wants to merge 1 commit intodevelopfrom
CU-86d1bqnbx-Adding-workflow-inside-workflow
Open

add existing sub-workflow inside workflow#201
rootflo-hardik wants to merge 1 commit intodevelopfrom
CU-86d1bqnbx-Adding-workflow-inside-workflow

Conversation

@rootflo-hardik
Copy link
Contributor

@rootflo-hardik rootflo-hardik commented Jan 5, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for workflows to reference and inline other workflows as subworkflows.
    • Workflow validation now automatically extracts and inlines subworkflow references during processing.
    • Integrated subworkflow resolution into the workflow creation flow.
  • Refactor

    • Enhanced workflow processing with caching for improved performance when accessing workflow definitions.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

📝 Walkthrough

Walkthrough

Two workflow service files are updated to support subworkflow inlining: extracting subworkflow references from YAML, fetching their definitions from cloud storage, and merging them into parent workflows before building instances through AriumBuilder.

Changes

Cohort / File(s) Summary
Subworkflow Inlining
wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py, workflow_inference_service.py
Added methods to extract subworkflow references from YAML (_extract_subworkflow_references), fetch workflow content from cloud storage (get_workflow_yaml_from_bucket), and inline subworkflow definitions into parent YAML (_inline_subworkflow_references). Integration into validation and workflow creation flows to resolve references before AriumBuilder construction.

Sequence Diagram

sequenceDiagram
    participant Client
    participant WorkflowService
    participant YAMLParser
    participant CloudStorage
    participant AriumBuilder

    Client->>WorkflowService: validate/create workflow with YAML
    WorkflowService->>YAMLParser: extract subworkflow references
    YAMLParser-->>WorkflowService: list of references (namespace/workflow_name)
    
    alt Has Subworkflow References
        loop For each reference
            WorkflowService->>CloudStorage: fetch subworkflow YAML
            CloudStorage-->>WorkflowService: subworkflow definition
        end
        
        rect rgb(200, 220, 240)
        Note over WorkflowService,YAMLParser: Inline References Phase
        WorkflowService->>YAMLParser: _inline_subworkflow_references()
        YAMLParser->>YAMLParser: merge subworkflow configs
        YAMLParser-->>WorkflowService: inlined YAML
        end
    end
    
    WorkflowService->>AriumBuilder: build with inlined YAML
    AriumBuilder-->>WorkflowService: workflow instance
    WorkflowService-->>Client: validated/created workflow
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Nested workflows now take flight,
References inlined, definitions tight,
From buckets deep we fetch and weave,
Subworkflows merged, none to grieve!
hop hop — recursion, pure delight! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding support for sub-workflows to be included/inlined inside parent workflows, which is the primary focus across both modified service files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link

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

Fix all issues with AI Agents 🤖
In
@wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py:
- Line 303: The shallow copy of subworkflow configs using
subworkflow_configs[arium_name].copy() can lead to mutations of cached configs;
replace the shallow copy with a deep copy by importing and using copy.deepcopy
when creating inline_config in workflow_crud_service (the assignment to
inline_config referencing subworkflow_configs and arium_name) so nested
structures are fully cloned and cached entries aren't mutated.

In
@wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py:
- Line 272: The current use of subworkflow_configs[arium_name].copy() creates a
shallow copy and can allow nested structures to be mutated; replace it with a
deep copy by importing the copy module and using
copy.deepcopy(subworkflow_configs[arium_name]) when assigning inline_config so
changes to inline_config (e.g., nested keys like 'agents' or 'workflow') won’t
mutate the cached subworkflow_configs entry.
♻️ Duplicate comments (1)
wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py (1)

88-122: Duplicate of workflow_inference_service.py implementation.

As noted in the other file, this method duplicates logic. The shared utility approach would benefit both services.

🧹 Nitpick comments (3)
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py (2)

109-143: Duplicate implementation with workflow_crud_service.py.

This method is nearly identical to _extract_subworkflow_references in workflow_crud_service.py (lines 88-122). Consider extracting this logic into a shared utility module to avoid code duplication and ensure consistent behavior across both services.

Suggested approach

Create a shared utility in agents_module/utils/workflow_utils.py:

def extract_subworkflow_references(yaml_content: str) -> List[str]:
    """Extract subworkflow references from workflow YAML."""
    # ... shared implementation

Then import and use it in both services.


220-290: Add recursive processing and circular reference detection for nested subworkflows

The current implementation only handles single-level subworkflow references. If a subworkflow contains references to other subworkflows, those nested references won't be inlined. Additionally, there's no detection for circular dependencies (e.g., A→B→A).

Consider:

  1. Recursively extracting and inlining subworkflow references from fetched YAML, or
  2. Adding a depth limit and tracking visited subworkflows to prevent circular reference issues
wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py (1)

238-244: Chain the exception for better debugging context.

When re-raising as ValueError, preserve the original exception chain to aid debugging.

Proposed fix
         except CloudStorageFileNotFoundError:
             logger.error(
                 f'YAML not found in cloud storage for workflow: {namespace}/{workflow_name}'
             )
-            raise ValueError(
+            raise ValueError(
                 f'Workflow YAML not found for workflow: {namespace}/{workflow_name}'
-            )
+            ) from None

Using from None explicitly suppresses the chain if the original exception isn't useful, or use from e to preserve it:

-        except CloudStorageFileNotFoundError:
+        except CloudStorageFileNotFoundError as e:
             ...
-            raise ValueError(...)
+            raise ValueError(...) from e
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da52a53 and 924dcf8.

📒 Files selected for processing (2)
  • wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py
  • wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py
🧰 Additional context used
🧬 Code graph analysis (2)
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py (1)
wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py (2)
  • _extract_subworkflow_references (88-122)
  • _inline_subworkflow_references (251-321)
wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py (1)
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py (2)
  • _extract_subworkflow_references (109-143)
  • _inline_subworkflow_references (220-290)
🪛 Ruff (0.14.10)
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py

140-140: Consider moving this statement to an else block

(TRY300)


141-141: Do not catch blind exception: Exception

(BLE001)


142-142: Use explicit conversion flag

Replace with conversion flag

(RUF010)

wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py

119-119: Consider moving this statement to an else block

(TRY300)


120-120: Do not catch blind exception: Exception

(BLE001)


121-121: Use explicit conversion flag

Replace with conversion flag

(RUF010)


242-244: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


242-244: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (2)
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py (1)

311-319: LGTM!

The subworkflow inlining is correctly placed before agent reference extraction, ensuring that agents defined in subworkflows are also properly resolved.

wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py (1)

343-351: LGTM!

The subworkflow inlining during validation ensures that referenced subworkflows are properly resolved and validated as part of the parent workflow.

logger.info(f'Inlining subworkflow: {arium_name}')

# Get the fetched subworkflow config
inline_config = subworkflow_configs[arium_name].copy()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same shallow copy concern as in workflow_inference_service.py.

Use copy.deepcopy() to avoid potential mutation of cached subworkflow configurations.

Proposed fix
-                inline_config = subworkflow_configs[arium_name].copy()
+                import copy
+                inline_config = copy.deepcopy(subworkflow_configs[arium_name])

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
@wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py
around line 303, The shallow copy of subworkflow configs using
subworkflow_configs[arium_name].copy() can lead to mutations of cached configs;
replace the shallow copy with a deep copy by importing and using copy.deepcopy
when creating inline_config in workflow_crud_service (the assignment to
inline_config referencing subworkflow_configs and arium_name) so nested
structures are fully cloned and cached entries aren't mutated.
logger.info(f'Inlining subworkflow: {arium_name}')

# Get the fetched subworkflow config
inline_config = subworkflow_configs[arium_name].copy()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Shallow copy may cause unintended side effects.

Using .copy() creates a shallow copy. If subworkflow_arium contains nested dictionaries (like agents, workflow, etc.), modifications to inline_config could mutate the cached original, causing subtle bugs in subsequent workflow builds.

Proposed fix
-                inline_config = subworkflow_configs[arium_name].copy()
+                import copy
+                inline_config = copy.deepcopy(subworkflow_configs[arium_name])

Or import copy at the top of the file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
inline_config = subworkflow_configs[arium_name].copy()
import copy
inline_config = copy.deepcopy(subworkflow_configs[arium_name])
🤖 Prompt for AI Agents
In
@wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py
around line 272, The current use of subworkflow_configs[arium_name].copy()
creates a shallow copy and can allow nested structures to be mutated; replace it
with a deep copy by importing the copy module and using
copy.deepcopy(subworkflow_configs[arium_name]) when assigning inline_config so
changes to inline_config (e.g., nested keys like 'agents' or 'workflow') won’t
mutate the cached subworkflow_configs entry.
logger.info(f'Found subworkflow reference: {arium_name}')

return subworkflow_references
except Exception as e:
Copy link
Member

Choose a reason for hiding this comment

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

Why are we catching this here ? Shouldnt we just throw exception, and let the caller know ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants