> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oration.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sub Flow

> Execute another published flow as a reusable step in your main flow

The **Sub Flow** node allows you to embed and execute another published flow as a nested component within your main flow. This enables code reuse, modular design, and simplified management of complex flow logic.

## Behavior

* Executes the referenced flow from start to end
* Inherits all dynamic variables and context from the parent flow
* Preserves the caller's context (phone number, conversation metadata, etc.)
* Waits for the sub-flow to complete before continuing to the next node in the main flow
* Supports arbitrary nesting depth (sub-flows within sub-flows)
* Automatically flattens during flow initialization for seamless execution

## When to use

Use Sub Flow nodes when you want to:

* **Reuse common sequences** across multiple flows (e.g., authentication, IVR menu trees)
* **Organize complex logic** into manageable, testable units
* **Simplify maintenance** by updating shared flows in one place
* **Compose flows dynamically** without duplicating node configurations
* **Share context** between flows (e.g., pass user data, authentication results, or preferences)

## Configuration

| Parameter | Type   | Required | Description                                           |
| --------- | ------ | -------- | ----------------------------------------------------- |
| `flowId`  | string | Yes      | The ID of the published flow to execute as a sub-flow |

## How it works

### Flow Resolution

During conversation initialization, the system performs automatic **flow resolution**:

1. **Discovery** — Scans the main flow for all `Sub Flow` node references
2. **Fetching** — Retrieves the referenced flows from the database (iteratively, handling nested sub-flows)
3. **Flattening** — Merges all sub-flow nodes and edges directly into the main flow
4. **Execution** — The XState actor runs one unified, flat flow with no sub-flow overhead

### Node Prefixing

When a sub-flow is embedded, all of its internal nodes are prefixed with the `Sub Flow` node's ID to ensure uniqueness. This allows:

* The same sub-flow to be embedded multiple times without ID collisions
* Deep nesting (sub-flow-of-sub-flow) with clear node identity chains
* Proper state tracking for each embedded instance

### Example Prefixing

```
Main Flow:
  [subflow-1] → mainFlow subFlow node → (embeds flow-auth)

After flattening:
  subflow-1__tts-node
  subflow-1__collect-digits
  subflow-1__condition-node
  ...
```

### Agent Hydration

If a sub-flow contains `Agent` nodes, they are automatically discovered and hydrated during flow initialization. This means:

* Agent configurations are loaded for all nested agent nodes
* Tools, LLM settings, and RAG configurations are applied before the flow runs
* The flow sees all agent nodes—regardless of nesting—as part of the unified graph

## Output handles

| Handle       | Description                                                                                   |
| ------------ | --------------------------------------------------------------------------------------------- |
| **Complete** | Sub-flow executed successfully and reached an end node — main flow continues to the next node |
| **Error**    | Sub-flow encountered an error or reached an error state                                       |

## Limitations and considerations

<AccordionGroup>
  <Accordion title="Circular references are detected">
    The system prevents cycles during flow initialization. If flow A references flow B and flow B references flow A, the conversation will fail at startup with a clear error message. Plan your flow hierarchy to avoid circular dependencies.
  </Accordion>

  <Accordion title="Sub-flow must have intermediate nodes">
    A sub-flow cannot contain only `Start` and `End` nodes—it must have at least one executable node (e.g., TTS, Agent, API Call). This ensures the flattened graph remains valid.
  </Accordion>

  <Accordion title="Performance scales linearly with nesting">
    Flow flattening is performed once at initialization time. Arbitrarily deep nesting (A → B → C → D) is supported and has minimal runtime overhead after flattening completes.
  </Accordion>

  <Accordion title="Published flows only">
    Only flows that are saved and published can be referenced by a `Sub Flow` node. Unsaved drafts cannot be used.
  </Accordion>

  <Accordion title="Variables are inherited, not isolated">
    Sub-flows share the same variable context as the parent flow. Any variables set by a sub-flow are visible to subsequent nodes in the main flow. There is no variable scope isolation.
  </Accordion>
</AccordionGroup>

## Use cases

<AccordionGroup>
  <Accordion title="Reusable authentication flow">
    Create a dedicated flow (e.g., `authenticate-customer`) that collects PIN, verifies it, and sets an `authenticated` flag. Embed this flow at the start of multiple customer-facing flows to ensure consistent authentication logic.

    **Flow structure:**

    ```
    Main Flow → Sub Flow (authenticate-customer) → [Authenticated branch logic]
    ```
  </Accordion>

  <Accordion title="Multi-tier IVR menu system">
    Create a modular menu hierarchy where each level is a separate flow:

    * `main-menu` — Primary options
    * `sales-menu` — Sales department options
    * `support-menu` — Support department options

    The main flow embeds `main-menu`, which in turn embeds `sales-menu` or `support-menu` based on the caller's selection.

    **Flow structure:**

    ```
    Main Flow
      → Sub Flow (main-menu)
        → IVR Menu [1: Sales, 2: Support]
        → Switch node routing to:
          → Sub Flow (sales-menu)
          → Sub Flow (support-menu)
    ```
  </Accordion>

  <Accordion title="Contextual handoff with AI agent">
    Create a `pre-agent-context` flow that gathers caller information (order number, issue type) and formats it for the agent. Embed this before an `Agent` node to ensure agents always receive pre-qualified context.

    **Flow structure:**

    ```
    Main Flow
      → Sub Flow (pre-agent-context)  [Collects and formats context]
      → Agent Node                     [Receives formatted context]
    ```
  </Accordion>

  <Accordion title="After-hours routing with fallback">
    Create a dedicated `after-hours-routing` flow that checks the time and routes to voicemail or an external service. Embed this at the end of your main flow to provide consistent off-hours behavior.

    **Flow structure:**

    ```
    Main Flow
      → Condition [Operating hours?]
      → If YES: Normal call handling
      → If NO: Sub Flow (after-hours-routing)
    ```
  </Accordion>

  <Accordion title="Multi-language support">
    Create language-specific flows (`flow-english`, `flow-spanish`, `flow-french`) with the same structure but localized audio/text. Use a Switch node on `caller.language` to embed the appropriate flow.

    **Flow structure:**

    ```
    Main Flow
      → Speech Input [Detect language]
      → Switch on language
        → Sub Flow (flow-english)
        → Sub Flow (flow-spanish)
        → Sub Flow (flow-french)
    ```
  </Accordion>
</AccordionGroup>

## Technical details

### Flow Flattening Algorithm

Sub-flows are resolved and flattened during conversation initialization (before the XState actor starts). The process:

1. **Scope-bound fetch** — Only flows referenced in the current conversation's main flow are fetched; this prevents unnecessary database queries
2. **Recursive resolution** — Nested sub-flows are discovered and fetched in an iterative process until no new flows are found
3. **Edge rewriting** — Incoming and outgoing edges are re-routed to maintain flow continuity:
   * Main flow edges targeting the sub-flow node now target the sub-flow's first real node
   * Sub-flow exit edges now target the main flow's original target
4. **ID prefixing** — All sub-flow nodes are prefixed to avoid collisions
5. **Flattened result** — A single, unified `FlowSchema` with no `Sub Flow` nodes is passed to the XState actor

### Error Handling

The system throws an error at initialization time if:

* A referenced flow does not exist in the database
* A flow is missing its `flowId` configuration
* A cycle is detected (A → B → A)
* A sub-flow is missing its `Start` or `End` node
* A sub-flow contains only `Start` and `End` with no intermediate nodes

Early error detection prevents runtime failures and makes debugging easier.

## Best practices

<Tip>
  **Organize flows hierarchically** — Create a naming convention (e.g., `base-*` for reusable flows, `main-*` for entry points) to make your flow library self-documenting.
</Tip>

<Tip>
  **Keep sub-flows focused** — Each sub-flow should have a single, well-defined purpose. Large, multi-purpose sub-flows are harder to test and reuse.
</Tip>

<Tip>
  **Test sub-flows independently** — Before embedding a sub-flow, test it as a standalone flow to ensure it works correctly.
</Tip>

<Tip>
  **Use descriptive flow names** — Instead of `flow-123`, use `authenticate-customer` or `qualify-sales-lead` so the purpose is clear in the editor.
</Tip>

<Tip>
  **Document shared context** — If a sub-flow expects or sets specific variables, document them clearly so integrators know what to provide and what they'll receive.
</Tip>
