diff --git a/flowpipe/node.py b/flowpipe/node.py
index 7fc825d..a9671e9 100644
--- a/flowpipe/node.py
+++ b/flowpipe/node.py
@@ -436,8 +436,13 @@ class FunctionNode(INode):
         metadata = copy.deepcopy(self.metadata)
         metadata.update(kwargs.pop("metadata", {}))
         graph = kwargs.pop('graph', 'default')
+        outputs = []
+        for o in self.outputs.values():
+            outputs.append(o.name)
+            for key in o._sub_plugs.keys():
+                outputs.append("{0}.{1}".format(o.name, key))
         return self.__class__(func=self.func,
-                              outputs=[o for o in self.outputs],
+                              outputs=outputs,
                               metadata=metadata,
                               graph=graph,
                               **kwargs)
@@ -511,7 +516,15 @@ class FunctionNode(INode):
 
         if outputs is not None:
             for output in outputs:
-                OutputPlug(output, self)
+                if "." in output:
+                    parent, subplug = output.split(".")
+                    parent_plug = self.outputs.get(parent)
+                    if parent_plug is None:
+                        parent_plug = OutputPlug(parent, self)
+                    SubOutputPlug(subplug, self, parent_plug)
+                else:
+                    if self.outputs.get(output) is None:
+                        OutputPlug(output, self)
 
     def to_pickle(self):  # pragma: no cover
         """Pickle the node. -- DOES NOT WORK FOR FunctionNode."""
diff --git a/flowpipe/plug.py b/flowpipe/plug.py
index b58e4c6..85e6f65 100644
--- a/flowpipe/plug.py
+++ b/flowpipe/plug.py
@@ -303,6 +303,7 @@ class SubInputPlug(IPlug):
             (OutputPlug, SubOutputPlug))
         self.key = key
         self.parent_plug = parent_plug
+        self.parent_plug._sub_plugs[key] = self
         self.value = value
         self.is_dirty = True
 
@@ -362,6 +363,7 @@ class SubOutputPlug(IPlug):
             (InputPlug, SubInputPlug))
         self.key = key
         self.parent_plug = parent_plug
+        self.parent_plug._sub_plugs[key] = self
         self.value = value
         self.is_dirty = True
 

Add sub output plugs through Node decorator
This should be made possible:

```python
@Node(outputs=["out.a", "out.b"])
MyNode():
    pass
```

Resulting in a node like this:

```
+-----------+
|  MyNode   |
+-----------+
|       out %
|    out.a  o
|    out.b  o
+-----------+
```
diff --git a/tests/test_convert_function_to_node.py b/tests/test_convert_function_to_node.py
index 2d84466..e99a8dc 100644
--- a/tests/test_convert_function_to_node.py
+++ b/tests/test_convert_function_to_node.py
@@ -182,3 +182,20 @@ def test_node_reserved_names():
         def function(func, name, identifier, inputs,
                      outputs, metadata, omit, graph):
             pass
+
+
+def test_create_node_with_sub_output_plugs():
+
+    @Node(outputs=["out.a", "out", "out.b"])
+    def function1(in_):
+        pass
+
+    node = function1(name="contains_all_plugs")
+    assert len(node.outputs["out"]._sub_plugs) == 2
+
+    @Node(outputs=["out.a", "out.b"])
+    def function2(in_):
+        pass
+
+    node = function2(name="contains_only_subplugs")
+    assert len(node.outputs["out"]._sub_plugs) == 2

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov mock coverage codacy-coverage doxypypy numpy
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
ascii-canvas==2.0.1
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
codacy-coverage==1.3.11
coverage==7.8.0
doxypypy==0.8.8.7
exceptiongroup==1.2.2
-e git+https://github.com/PaulSchweizer/flowpipe.git@06cade8408791fde0ab422c19d5d8e73facbc234#egg=flowpipe
idna==3.10
iniconfig==2.1.0
mock==5.2.0
numpy==2.0.2
ordereddict==1.1
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
pytest-cov==6.0.0
requests==2.32.3
strip-hints==0.1.13
tomli==2.2.1
urllib3==2.3.0

name: flowpipe
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - ascii-canvas==2.0.1
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - codacy-coverage==1.3.11
      - coverage==7.8.0
      - doxypypy==0.8.8.7
      - exceptiongroup==1.2.2
      - idna==3.10
      - iniconfig==2.1.0
      - mock==5.2.0
      - numpy==2.0.2
      - ordereddict==1.1
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - requests==2.32.3
      - strip-hints==0.1.13
      - tomli==2.2.1
      - urllib3==2.3.0
prefix: /opt/conda/envs/flowpipe

tests/test_convert_function_to_node.py::test_create_node_with_sub_output_plugs
tests/test_convert_function_to_node.py::test_input_plugs_are_taken_from_func_inputs tests/test_convert_function_to_node.py::test_name_is_taken_from_func_name_if_not_provided tests/test_convert_function_to_node.py::test_name_can_be_provided_as_kwarg tests/test_convert_function_to_node.py::test_doc_is_taken_from_func tests/test_convert_function_to_node.py::test_define_outputs tests/test_convert_function_to_node.py::test_decorator_returns_node_instances tests/test_convert_function_to_node.py::test_serialize_function_node tests/test_convert_function_to_node.py::test_use_self_as_first_arg_if_present tests/test_convert_function_to_node.py::test_assign_input_args_to_function_input_plugs tests/test_convert_function_to_node.py::test_provide_custom_node_class tests/test_convert_function_to_node.py::test_passing_metadata_updates_exisiting_metadata tests/test_convert_function_to_node.py::test_default_args_are_assigned_to_input_plugs tests/test_convert_function_to_node.py::test_metadata_is_unique_for_each_node_created tests/test_convert_function_to_node.py::test_class_name_restored_after_deserialization tests/test_convert_function_to_node.py::test_node_reserved_names
flowpipe/node.py flowpipe/plug.py
flowpipe/node.py flowpipe/plug.py