Skip to content

add existing sub-workflow inside workflow#201

Merged
vizsatiz merged 4 commits into
developfrom
CU-86d1bqnbx-Adding-workflow-inside-workflow
May 31, 2026
Merged

add existing sub-workflow inside workflow#201
vizsatiz merged 4 commits into
developfrom
CU-86d1bqnbx-Adding-workflow-inside-workflow

Conversation

@rootflo-hardik
Copy link
Copy Markdown
Contributor

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

Summary by CodeRabbit

  • New Features

    • Workflows can reference and inline other workflows as subworkflows; validation and creation now resolve and incorporate those references.
  • Refactor

    • Agent inference now resolves LLM configuration from agent YAML (v2) and no longer accepts an external LLM config override from the request.
  • Chores

    • Improved YAML parsing, detection/fetching/inlining logging, and performance-related caching for workflow YAML retrieval.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 5, 2026

📝 Walkthrough

Walkthrough

Two workflow service files now detect referenced subworkflows in arium.ariums, fetch their YAML from storage, inline those arium blocks into the parent YAML (preserving inherit_variables and normalizing names), and run validation/creation with the inlined YAML before building via AriumBuilder.

Changes

Subworkflow Inlining

Layer / File(s) Summary
Detect subworkflow references
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py
YAML parsing updated; detection logic added to identify arium.ariums entries referencing namespace/workflow_name and log found references.
Fetch and inline subworkflows
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py
New inlining helper fetches referenced workflow YAMLs, extracts their arium configs, preserves inherit_variables, normalizes inlined name, replaces matching parent entries, and serializes the modified YAML.
Integrate inlining into creation/validation
wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py, wavefront/server/modules/agents_module/agents_module/services/workflow_crud_service.py
Subworkflow extraction and inlining are invoked at the start of workflow creation/validation flows so agent extraction and AriumBuilder construction use the inlined YAML.
Agent v2 LLM resolution and API
wavefront/server/modules/agents_module/agents_module/services/agent_inference_service.py
AgentInferenceService now accepts an optional llm_inference_config_service, adds _resolve_rootflo_llm_config to parse YAML and fetch rootflo model configs by UUID via the service, and wires resolution into perform_inference_v2.
Controller v2 endpoint changes
wavefront/server/modules/agents_module/agents_module/controllers/agent_controller.py
agent_inference_v2 no longer injects llm_inference_config_service; endpoint docstring updated to state YAML-based LLM resolution and that payload llm_inference_config_id is ignored; handler no longer fetches or passes external LLM config.
DI container and server wiring
wavefront/server/modules/agents_module/agents_module/agents_container.py, wavefront/server/apps/floware/floware/server.py
Add llm_inference_config_service provider to AgentsContainer, pass it into agent_inference_service, and initialize/wire inference containers earlier in server startup.

Sequence Diagram

sequenceDiagram
    participant Client
    participant WorkflowInferenceService
    participant CloudStorage
    participant YAMLParser
    participant AriumBuilder

    Client->>WorkflowInferenceService: create/validate workflow (YAML)
    WorkflowInferenceService->>YAMLParser: parse YAML and extract arium.ariums
    YAMLParser-->>WorkflowInferenceService: arium entries
    WorkflowInferenceService->>WorkflowInferenceService: detect subworkflow references
    alt Has Subworkflow References
        loop For each reference
            WorkflowInferenceService->>CloudStorage: fetch referenced workflow YAML
            CloudStorage-->>WorkflowInferenceService: referenced YAML
            WorkflowInferenceService->>YAMLParser: extract referenced arium config
            YAMLParser-->>WorkflowInferenceService: arium config
        end
        WorkflowInferenceService->>YAMLParser: inline referenced arium configs into parent YAML (preserve inherit_variables, normalize names)
        YAMLParser-->>WorkflowInferenceService: inlined YAML
    end
    WorkflowInferenceService->>AriumBuilder: build workflow from inlined YAML
    AriumBuilder-->>WorkflowInferenceService: workflow instance
    WorkflowInferenceService-->>Client: return workflow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through YAML, fields aglow,
Fetching nests where subworkflows grow,
I stitched their arium into one,
So builders run and tests can run—hop!
🌱✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add existing sub-workflow inside workflow' accurately reflects the main objective of the PR, which is to enable inlining and referencing of existing subworkflows within parent workflows across multiple services.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ 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 CU-86d1bqnbx-Adding-workflow-inside-workflow

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
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: 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
Copy Markdown

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
Copy Markdown

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
Copy Markdown
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 ?

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: 0

🧹 Nitpick comments (1)
wavefront/server/modules/agents_module/agents_module/controllers/agent_controller.py (1)

151-154: 💤 Low value

Consider logging a warning when llm_inference_config_id is provided in v2 requests.

The docstring correctly states that llm_inference_config_id is ignored in v2, but the field is silently discarded if provided in the payload. This could confuse users migrating from v1 to v2 or using incorrect API versions.

Consider adding a log warning to help users detect misuse:

📋 Suggested addition

After line 169, add:

 # Process inputs using common utility function
 resolved_inputs = process_inference_inputs(agent_inference_payload.inputs)
+
+if agent_inference_payload.llm_inference_config_id:
+    logger.warning(
+        f"llm_inference_config_id provided in v2 request but will be ignored. "
+        f"LLM is resolved from agent YAML. agent_id: {agent_id}"
+    )
 
 try:
🤖 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
`@wavefront/server/modules/agents_module/agents_module/controllers/agent_controller.py`
around lines 151 - 154, Add a warning log when a v2 request payload includes
llm_inference_config_id even though it is ignored; in agent_controller.py,
inside the code path that resolves the LLM from the agent YAML (the branch where
agent.model.provider == "rootflo" and v2 behavior applies), detect if payload
contains llm_inference_config_id and emit a logger.warning including the agent
identifier and that llm_inference_config_id is ignored in v2; do not change
existing resolution logic—only add the non-breaking warning log so users are
informed when they supply the ignored llm_inference_config_id.
🤖 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.

Nitpick comments:
In
`@wavefront/server/modules/agents_module/agents_module/controllers/agent_controller.py`:
- Around line 151-154: Add a warning log when a v2 request payload includes
llm_inference_config_id even though it is ignored; in agent_controller.py,
inside the code path that resolves the LLM from the agent YAML (the branch where
agent.model.provider == "rootflo" and v2 behavior applies), detect if payload
contains llm_inference_config_id and emit a logger.warning including the agent
identifier and that llm_inference_config_id is ignored in v2; do not change
existing resolution logic—only add the non-breaking warning log so users are
informed when they supply the ignored llm_inference_config_id.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b74e8456-4bc6-4351-8b09-4f016ab023e2

📥 Commits

Reviewing files that changed from the base of the PR and between 4e127ac and 666aec8.

📒 Files selected for processing (5)
  • wavefront/server/apps/floware/floware/server.py
  • wavefront/server/modules/agents_module/agents_module/agents_container.py
  • wavefront/server/modules/agents_module/agents_module/controllers/agent_controller.py
  • wavefront/server/modules/agents_module/agents_module/services/agent_inference_service.py
  • wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py
💤 Files with no reviewable changes (2)
  • wavefront/server/modules/agents_module/agents_module/services/agent_inference_service.py
  • wavefront/server/modules/agents_module/agents_module/services/workflow_inference_service.py

@vizsatiz vizsatiz merged commit e18118f into develop May 31, 2026
9 checks passed
@vizsatiz vizsatiz deleted the CU-86d1bqnbx-Adding-workflow-inside-workflow branch May 31, 2026 16:29
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