Define Control-Flow and Data-Flow Edges

A Flow uses two independent kinds of connections. Control-flow edges describe the nodes that can execute after a node completes. Data-flow edges transfer named values between declared component outputs and inputs.

Most Flows use both kinds of connections, but they serve different purposes:

ConnectionDescribes
ControlFlowEdgeA possible control continuation from one node to another.
DataFlowEdgeThe transfer of one named output value to one named input.

These relationships are explicit. Matching node or input names do not create a connection, and a control-flow edge does not imply a corresponding data-flow edge.

ControlFlowEdge

A ControlFlowEdge identifies a source node, a destination node, and, where applicable, a branch selected by the source node. After the source node completes, the edge describes a destination that can execute next.

ControlFlowEdge Fields

FieldRequirementDescription
component_typeRequiredIdentifies the component as a ControlFlowEdge.
idRequiredUniquely identifies the edge within its component scope.
nameRequiredProvides a human-readable component name.
from_nodeRequiredReferences the node from which control can continue.
to_nodeRequiredReferences a node that can execute when this edge applies.
from_branchOptionalIdentifies the source branch associated with this edge.

The following edge describes process-request as a possible next node after start completes:

{
  "component_type": "ControlFlowEdge",
  "id": "start-to-process-request",
  "name": "start_to_process_request",
  "from_node": {
    "$component_ref": "start"
  },
  "to_node": {
    "$component_ref": "process-request"
  }
}

from_node and to_node must resolve to nodes in the same Flow graph. The edge describes a control relationship only; it does not supply any input values required by process-request.

Branch-Specific Control Flow

A node with multiple control branches can have several outgoing ControlFlowEdge components. Each edge uses from_branch to associate one declared branch with a possible next node.

For example, the following edges connect the eligible and ineligible branches of check-return-eligibility to different nodes:

[
  {
    "component_type": "ControlFlowEdge",
    "id": "eligibility-to-create-return",
    "name": "eligibility_to_create_return",
    "from_node": {
      "$component_ref": "check-return-eligibility"
    },
    "from_branch": "eligible",
    "to_node": {
      "$component_ref": "create-return"
    }
  },
  {
    "component_type": "ControlFlowEdge",
    "id": "eligibility-to-explain-denial",
    "name": "eligibility_to_explain_denial",
    "from_node": {
      "$component_ref": "check-return-eligibility"
    },
    "from_branch": "ineligible",
    "to_node": {
      "$component_ref": "explain-denial"
    }
  }
]

Every declared branch that can be selected must have an outgoing ControlFlowEdge whose from_node references the branching node and whose from_branch has the exact same name. Control through each branch must eventually reach an EndNode.

Selecting a branch does not transfer values to its destination. Separate data-flow edges supply the inputs required by the node on that branch.

FlowNode Branches

A FlowNode can select a branch according to the branch_name of the EndNode reached in its subflow. An outgoing control-flow edge in the enclosing Flow uses that branch name in from_branch to describe the possible continuation.

The EndNode belongs to the subflow graph and is not referenced by control-flow edges in the enclosing Flow. Instead, an outgoing edge in the enclosing Flow references the FlowNode in from_node and uses the EndNode's branch_name in from_branch. For more information, see Subflow Completion and Branch Selection.

DataFlowEdge

A DataFlowEdge transfers one value from a declared source output to a declared destination input. It identifies both components and the named output and input involved in the transfer.

DataFlowEdge Fields

FieldRequirementDescription
component_typeRequiredIdentifies the component as a DataFlowEdge.
idRequiredUniquely identifies the edge within its component scope.
nameRequiredProvides a human-readable component name.
source_nodeRequiredReferences the component that produces the value.
source_outputRequiredNames an output declared by the source component.
destination_nodeRequiredReferences the component that receives the value.
destination_inputRequiredNames an input declared by the destination component.

The following edge transfers order_id from start to lookup-order:

{
  "component_type": "DataFlowEdge",
  "id": "order-id-to-lookup",
  "name": "order_id_to_lookup",
  "source_node": {
    "$component_ref": "start"
  },
  "source_output": "order_id",
  "destination_node": {
    "$component_ref": "lookup-order"
  },
  "destination_input": "order_id"

The endpoint names are case-sensitive and must exist in the applicable input and output contracts. The runtime validates that the transferred value conforms to the destination input declaration.

The edge makes order_id available to lookup-order, but it does not determine when lookup-order can execute.

Independent Control and Data Connections

Control-flow and data-flow edges do not require a one-to-one correspondence. A value can pass directly from its producer to a later consumer without being copied through every node on the control path.

Consider an order-support Flow that validates a request, looks up the order, formats a response, and then completes:

Description of the illustration Control-Flow and Data-Flow Edge Mapping

The corresponding control-flow connections are:

[
  {
    "component_type": "ControlFlowEdge",
    "id": "start-to-validate",
    "name": "start_to_validate",
    "from_node": {
      "$component_ref": "start"
    },
    "to_node": {
      "$component_ref": "validate-request"
    }
  },
  {
    "component_type": "ControlFlowEdge",
    "id": "validate-to-lookup",
    "name": "validate_to_lookup",
    "from_node": {
      "$component_ref": "validate-request"
    },
    "to_node": {
      "$component_ref": "lookup-order"
    }
  },
  {
    "component_type": "ControlFlowEdge",
    "id": "lookup-to-format",
    "name": "lookup_to_format",
    "from_node": {
      "$component_ref": "lookup-order"
    },
    "to_node": {
      "$component_ref": "format-response"
    }
  },
  {
    "component_type": "ControlFlowEdge",
    "id": "format-to-end",
    "name": "format_to_end",
    "from_node": {
      "$component_ref": "format-response"
    },
    "to_node": {
      "$component_ref": "end"
    }
  }
]

The data-flow connections are:

[
  {
    "component_type": "DataFlowEdge",
    "id": "request-to-validation",
    "name": "request_to_validation",
    "source_node": {
      "$component_ref": "start"
    },
    "source_output": "request",
    "destination_node": {
      "$component_ref": "validate-request"
    },
    "destination_input": "request"
  },
  {
    "component_type": "DataFlowEdge",
    "id": "order-id-to-lookup",
    "name": "order_id_to_lookup",
    "source_node": {
      "$component_ref": "start"
    },
    "source_output": "order_id",
    "destination_node": {
      "$component_ref": "lookup-order"
    },
    "destination_input": "order_id"
  },
  {
    "component_type": "DataFlowEdge",
    "id": "request-to-formatter",
    "name": "request_to_formatter",
    "source_node": {
      "$component_ref": "start"
    },
    "source_output": "request",
    "destination_node": {
      "$component_ref": "format-response"
    },
    "destination_input": "request"
  },
  {
    "component_type": "DataFlowEdge",
    "id": "status-to-formatter",
    "name": "status_to_formatter",
    "source_node": {
      "$component_ref": "lookup-order"
    },
    "source_output": "order_status",
    "destination_node": {
      "$component_ref": "format-response"
    },
    "destination_input": "order_status"
  },
  {
    "component_type": "DataFlowEdge",
    "id": "response-to-end",
    "name": "response_to_end",
    "source_node": {
      "$component_ref": "format-response"
    },
    "source_output": "response",
    "destination_node": {
      "$component_ref": "end"
    },
    "destination_input": "response"
  }
]

During execution:

  1. The start-to-validate control-flow edge identifies validate-request as the first possible node after start.
  2. The request-to-validation data-flow edge supplies the request required by validate-request.
  3. After validation completes, the validate-to-lookup control-flow edge identifies lookup-order as a possible next node.
  4. lookup-order.order_id comes directly from start.order_id; the validation node does not need to accept and republish that value.
  5. format-response receives the original request directly from start and the order status from lookup-order.
  6. After control reaches format-response, both values are available through its declared inputs.
  7. The formatted response is transferred to end.response, and control continues to end through the separate format-to-end edge.

This separation avoids pass-through inputs and outputs on nodes that do not use or transform a value. Each node declares only the data it consumes or produces, while the control graph independently describes the possible execution sequence.