diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index c5e4e97faaf11c65a6cab597e1563e31ba74e7f5..fb72c6573b9cd77a3ffc85253efbc303ca9db1d1 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -4,14 +4,16 @@ init class that imports all workflows into GSO.
 from orchestrator.workflows import LazyWorkflowInstance
 
 LazyWorkflowInstance("gso.workflows.device.create_device", "create_device")
-LazyWorkflowInstance("gso.workflows.device.terminate_device",
-                     "terminate_device")
+LazyWorkflowInstance(
+    "gso.workflows.device.terminate_device", "terminate_device"
+)
 LazyWorkflowInstance("gso.workflows.device.get_facts", "get_facts")
 LazyWorkflowInstance("gso.workflows.iptrunk.create_iptrunk", "create_iptrunk")
-LazyWorkflowInstance("gso.workflows.iptrunk.terminate_iptrunk",
-                     "terminate_iptrunk")
-LazyWorkflowInstance("gso.workflows.iptrunk.modify_isis_metric",
-                     "modify_isis_metric")
-LazyWorkflowInstance("gso.workflows.iptrunk.modify_generic",
-                     "modify_generic")
+LazyWorkflowInstance(
+    "gso.workflows.iptrunk.terminate_iptrunk", "terminate_iptrunk"
+)
+LazyWorkflowInstance(
+    "gso.workflows.iptrunk.modify_isis_metric", "modify_isis_metric"
+)
+LazyWorkflowInstance("gso.workflows.iptrunk.modify_generic", "modify_generic")
 LazyWorkflowInstance("gso.workflows.site.create_site", "create_site")
diff --git a/gso/workflows/device/get_facts.py b/gso/workflows/device/get_facts.py
index 024631740dfbfacd229a1d442d26c0d274af5e8e..a50caee3a8fe3eba6811107615d1eca0f2ea58c4 100644
--- a/gso/workflows/device/get_facts.py
+++ b/gso/workflows/device/get_facts.py
@@ -1,9 +1,11 @@
 from orchestrator.forms import FormPage
 from orchestrator.forms.validators import Label
 from orchestrator.targets import Target
+
 # from orchestrator.types import SubscriptionLifecycle
 from orchestrator.types import InputForm, UUIDstr
 from orchestrator.workflow import done, init, step, workflow
+
 # from orchestrator.workflows.steps import (
 #     resync,
 #     set_status,
@@ -21,10 +23,8 @@ def initial_input_form_generator(
     subscription = Device.from_subscription(subscription_id)
 
     class TerminateForm(FormPage):
-        are_you_sure: Label = (
-            f"Are you sure you want to get facts from \
+        are_you_sure: Label = f"Are you sure you want to get facts from \
             {subscription.description}?"
-        )
 
     return TerminateForm
 
@@ -48,7 +48,8 @@ def get_facts(subscription_id) -> None:
 @workflow(
     "Get Facts from Device",
     initial_input_form=wrap_modify_initial_input_form(
-                       initial_input_form_generator),
+        initial_input_form_generator
+    ),
     target=Target.SYSTEM,
 )
 def get_facts_from_device():
diff --git a/gso/workflows/iptrunk/modify_generic.py b/gso/workflows/iptrunk/modify_generic.py
new file mode 100644
index 0000000000000000000000000000000000000000..9c3c633c352be9c555ca6afa39d92b58bb3ffcfe
--- /dev/null
+++ b/gso/workflows/iptrunk/modify_generic.py
@@ -0,0 +1,240 @@
+import ipaddress
+from orchestrator.forms import FormPage, ReadOnlyField
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State
+from orchestrator.types import UUIDstr
+from orchestrator.workflow import done, init, step, workflow
+from orchestrator.workflows.steps import resync
+from orchestrator.workflows.steps import store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from orchestrator.forms.validators import Choice, UniqueConstrainedList
+from gso.products.product_blocks.iptrunk import IptrunkType
+from gso.products.product_blocks import PhyPortCapacity
+
+from gso.products.product_types.iptrunk import (
+    Iptrunk,
+)
+from gso.services import provisioning_proxy
+from gso.services.provisioning_proxy import (
+    confirm_pp_results,
+    await_pp_results,
+)
+
+
+def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
+    subscription = Iptrunk.from_subscription(subscription_id)
+
+    class ModifyIptrunkForm(FormPage):
+        geant_s_sid: str = subscription.iptrunk.geant_s_sid
+        iptrunk_description: str = subscription.iptrunk.iptrunk_description
+        iptrunk_type: IptrunkType = subscription.iptrunk.iptrunk_type
+        iptrunk_speed: PhyPortCapacity = subscription.iptrunk.iptrunk_speed
+        iptrunk_minimum_links: int = subscription.iptrunk.iptrunk_minimum_links
+        iptrunk_isis_metric: int = ReadOnlyField(
+            subscription.iptrunk.iptrunk_isis_metric
+        )
+        iptrunk_ipv4_network: ipaddress.IPv4Network = ReadOnlyField(
+            subscription.iptrunk.iptrunk_ipv4_network
+        )
+        iptrunk_ipv6_network: ipaddress.IPv6Network = ReadOnlyField(
+            subscription.iptrunk.iptrunk_ipv6_network
+        )
+
+    initial_user_input = yield ModifyIptrunkForm
+
+    class AeMembersListA(UniqueConstrainedList[str]):
+        min_items = initial_user_input.iptrunk_minimum_links
+
+    class ModifyIptrunkSideAForm(FormPage):
+        class Config:
+            title = "Provide subscription details for side A of the trunk."
+
+        iptrunk_sideA_node: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideA_node.device_fqdn
+        )
+        iptrunk_sideA_ae_iface: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideA_ae_iface
+        )
+        iptrunk_sideA_ae_geant_a_sid: str = (
+            subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid
+        )
+        iptrunk_sideA_ae_members: AeMembersListA = (
+            subscription.iptrunk.iptrunk_sideA_ae_members
+        )
+        iptrunk_sideA_ae_members_descriptions: AeMembersListA = (
+            subscription.iptrunk.iptrunk_sideA_ae_members_description
+        )
+
+    user_input_side_a = yield ModifyIptrunkSideAForm
+
+    class AeMembersListB(UniqueConstrainedList[str]):
+        min_items = len(user_input_side_a.iptrunk_sideA_ae_members)
+        max_items = len(user_input_side_a.iptrunk_sideA_ae_members)
+
+    class ModifyIptrunkSideBForm(FormPage):
+        class Config:
+            title = "Provide subscription details for side B of the trunk."
+
+        iptrunk_sideB_node: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideB_node.device_fqdn
+        )
+        iptrunk_sideB_ae_iface: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideB_ae_iface
+        )
+        iptrunk_sideB_ae_geant_a_sid: str = (
+            subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid
+        )
+        iptrunk_sideB_ae_members: AeMembersListB = (
+            subscription.iptrunk.iptrunk_sideB_ae_members
+        )
+        iptrunk_sideB_ae_members_descriptions: AeMembersListB = (
+            subscription.iptrunk.iptrunk_sideB_ae_members_description
+        )
+
+    user_input_side_b = yield ModifyIptrunkSideBForm
+
+    return (
+        initial_user_input.dict()
+        | user_input_side_a.dict()
+        | user_input_side_b.dict()
+    )
+
+
+@step("Update subscription")
+def modify_iptrunk_subscription(
+    subscription: Iptrunk,
+    geant_s_sid: str,
+    iptrunk_type: IptrunkType,
+    iptrunk_description: str,
+    iptrunk_speed: str,
+    iptrunk_minimum_links: int,
+    iptrunk_sideA_ae_geant_a_sid: str,
+    iptrunk_sideA_ae_members: list[str],
+    iptrunk_sideA_ae_members_descriptions: list[str],
+    iptrunk_sideB_ae_geant_a_sid: str,
+    iptrunk_sideB_ae_members: list[str],
+    iptrunk_sideB_ae_members_descriptions: list[str],
+) -> State:
+    subscription.iptrunk.geant_s_sid = geant_s_sid
+    subscription.iptrunk.iptrunk_description = iptrunk_description
+    subscription.iptrunk.iptrunk_type = iptrunk_type
+    subscription.iptrunk.iptrunk_speed = iptrunk_speed
+    subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
+
+    subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid = (
+        iptrunk_sideA_ae_geant_a_sid
+    )
+    subscription.iptrunk.iptrunk_sideA_ae_members = iptrunk_sideA_ae_members
+    subscription.iptrunk.iptrunk_sideA_ae_members_description = (
+        iptrunk_sideA_ae_members_descriptions
+    )
+
+    subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid = (
+        iptrunk_sideB_ae_geant_a_sid
+    )
+    subscription.iptrunk.iptrunk_sideB_ae_members = iptrunk_sideB_ae_members
+    subscription.iptrunk.iptrunk_sideB_ae_members_description = (
+        iptrunk_sideB_ae_members_descriptions
+    )
+
+    subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}"
+
+    return {"subscription": subscription}
+
+
+@step("Provision IP trunk interface [DRY RUN]")
+def provision_ip_trunk_iface_dry(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "trunk_interface"
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the Trunk interface [DRY] "
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk interface [FOR REAL]")
+def provision_ip_trunk_iface_real(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "trunk_interface", False
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the Trunk interface [REAL] "
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk LLDP interface [DRY RUN]")
+def provision_ip_trunk_lldp_iface_dry(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "lldp_interface"
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the LLDP interface [DRY]"
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk LLDP interface [FOR REAL]")
+def provision_ip_trunk_lldp_iface_real(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "lldp_interface", False
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the LLDP interface [REAL]"
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@workflow(
+    "Modify IP trunk",
+    initial_input_form=wrap_modify_initial_input_form(
+        initial_input_form_generator
+    ),
+    target=Target.MODIFY,
+)
+def modify_generic():
+    return (
+        init
+        >> store_process_subscription(Target.MODIFY)
+        >> unsync
+        >> modify_iptrunk_subscription
+        >> provision_ip_trunk_iface_dry
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_iface_real
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_lldp_iface_dry
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_lldp_iface_real
+        >> await_pp_results
+        >> confirm_pp_results
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py
index aa92be43b8c11bdddf0aa99e819f45916447ffb1..0773d71c3ccdea5103211dabd94358d73201658b 100644
--- a/gso/workflows/site/create_site.py
+++ b/gso/workflows/site/create_site.py
@@ -45,16 +45,16 @@ def create_subscription(product: UUIDstr) -> State:
 
 @step("Initialize subscription")
 def initialize_subscription(
-        subscription: site.SiteInactive,
-        site_name: str,
-        site_city: str,
-        site_country: str,
-        site_country_code: str,
-        site_latitude: float,
-        site_longitude: float,
-        site_bgp_community_id: int,
-        site_internal_id: int,
-        site_tier: site_pb.SiteTier
+    subscription: site.SiteInactive,
+    site_name: str,
+    site_city: str,
+    site_country: str,
+    site_country_code: str,
+    site_latitude: float,
+    site_longitude: float,
+    site_bgp_community_id: int,
+    site_internal_id: int,
+    site_tier: site_pb.SiteTier,
 ) -> State:
     subscription.site.site_name = site_name
     subscription.site.site_city = site_city
@@ -78,16 +78,17 @@ def initialize_subscription(
 @workflow(
     "Create Site",
     initial_input_form=wrap_create_initial_input_form(
-        initial_input_form_generator),
+        initial_input_form_generator
+    ),
     target=Target.CREATE,
 )
 def create_site():
     return (
-            init
-            >> create_subscription
-            >> store_process_subscription(Target.CREATE)
-            >> initialize_subscription
-            >> set_status(SubscriptionLifecycle.ACTIVE)
-            >> resync
-            >> done
+        init
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
     )