diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py
index 11068bac93dc6eb1492e545a9cdd5a674c926187..d22b3e33a6cc76bbc2a037525375ae0c58c74582 100644
--- a/gso/services/provisioning_proxy.py
+++ b/gso/services/provisioning_proxy.py
@@ -7,13 +7,14 @@ import logging
 from typing import NoReturn
 
 import requests
-from orchestrator import inputstep
+from orchestrator import inputstep, conditional, step
 from orchestrator.config.assignee import Assignee
 from orchestrator.domain import SubscriptionModel
 from orchestrator.forms import FormPage, ReadOnlyField
 from orchestrator.forms.validators import Accept, Label, LongText
 from orchestrator.types import FormGenerator, State, UUIDstr, strEnum
 from orchestrator.utils.json import json_dumps
+from orchestrator.workflow import Step, StepList
 from pydantic import validator
 
 from gso import settings
@@ -162,8 +163,15 @@ def await_pp_results(subscription: SubscriptionModel, label_text: str = DEFAULT_
     return result_page.dict()
 
 
+@step("Reset Provisioning Proxy state")
+def reset_pp_success_state() -> State:
+    return {"pp_did_succeed": False}
+
+
 @inputstep("Confirm provisioning proxy results", assignee=Assignee("SYSTEM"))
 def confirm_pp_results(state: State) -> FormGenerator:
+    successful_run = state["pp_run_results"]["return_code"] == 0
+
     class ConfirmRunPage(FormPage):
         class Config:
             title = (
@@ -174,9 +182,21 @@ def confirm_pp_results(state: State) -> FormGenerator:
 
         run_status: str = ReadOnlyField(state["pp_run_results"]["status"])
         run_results: LongText = ReadOnlyField(f"{state['pp_run_results']['output']}")
-        pp_result_good_enough: bool = state["pp_run_results"]["return_code"] == 0
+        if not successful_run:
+            pp_retry_label: Label = "Provisioning Proxy has failed execution, the playbook will be retried " \
+                                    "(up to two times)."
         confirm: Accept = Accept("INCOMPLETE")
 
-    confirmation = yield ConfirmRunPage
+    yield ConfirmRunPage
+
+    return {"pp_did_succeed": successful_run}
+
+
+def pp_interaction(provisioning_step: Step) -> StepList:
+    should_retry_pp_steps = conditional(lambda state: not state.get("pp_did_succeed"))
 
-    return {"pp_did_succeed": confirmation.pp_result_good_enough}
+    return (
+        should_retry_pp_steps(provisioning_step)
+        >> should_retry_pp_steps(await_pp_results)
+        >> should_retry_pp_steps(confirm_pp_results)
+    )
diff --git a/gso/translations/en-GB.json b/gso/translations/en-GB.json
index ea950f27471b99b21b4a8b1121fc2ef9a1df85b8..845ad7320d7e87cdd38aa78a51eacc61f9270eec 100644
--- a/gso/translations/en-GB.json
+++ b/gso/translations/en-GB.json
@@ -5,8 +5,7 @@
             "confirm_info": "Please verify this form looks correct.",
 
             "pp_run_results": "Provisioning proxy results are not ready yet.",
-            "pp_result_good_enough": "Provisioning Proxy results look good (enough).",
-            "pp_result_good_enough_info": "If set to false, this will retry the provisioning up to two times.",
+            "pp_retry_label": "Playbook execution failure",
 
             "site_bgp_community_id": "Site BGP community ID",
             "site_internal_id": "Site internal ID",
diff --git a/gso/workflows/device/create_device.py b/gso/workflows/device/create_device.py
index cab0f3230a71243a7b642160018b85c2c317a090..1a3bb302ed4506d65da51f9030d073903e840128 100644
--- a/gso/workflows/device/create_device.py
+++ b/gso/workflows/device/create_device.py
@@ -9,7 +9,7 @@ from orchestrator.forms import FormPage
 from orchestrator.forms.validators import Choice
 from orchestrator.targets import Target
 from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr
-from orchestrator.workflow import StepList, conditional, done, init, step, workflow
+from orchestrator.workflow import StepList, done, init, step, workflow
 from orchestrator.workflows.steps import resync, set_status, store_process_subscription
 from orchestrator.workflows.utils import wrap_create_initial_input_form
 
@@ -18,7 +18,7 @@ from gso.products.product_types import device
 from gso.products.product_types.device import DeviceInactive, DeviceProvisioning
 from gso.products.product_types.site import Site
 from gso.services import _ipam, provisioning_proxy
-from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results
+from gso.services.provisioning_proxy import reset_pp_success_state, pp_interaction
 
 
 def site_selector() -> Choice:
@@ -118,7 +118,7 @@ def initialize_subscription(
 
     subscription = device.DeviceProvisioning.from_other_lifecycle(subscription, SubscriptionLifecycle.PROVISIONING)
 
-    return {"subscription": subscription, "pp_did_succeed": False}
+    return {"subscription": subscription}
 
 
 @step("Provision device [DRY RUN]")
@@ -153,50 +153,29 @@ def provision_device_real(subscription: DeviceProvisioning, process_id: UUIDstr)
     }
 
 
-@step("Reset Provisioning Proxy state")
-def reset_pp_success_state() -> State:
-    return {"pp_did_succeed": False}
-
-
 @workflow(
     "Create device",
     initial_input_form=wrap_create_initial_input_form(initial_input_form_generator),
     target=Target.CREATE,
 )
 def create_device() -> StepList:
-    should_retry_pp_steps = conditional(lambda state: not state.get("pp_did_succeed"))
-
     return (
         init
         >> create_subscription
         >> store_process_subscription(Target.CREATE)
         >> initialize_subscription
         >> get_info_from_ipam
-        # First attempt at dry run
-        >> should_retry_pp_steps(provision_device_dry)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
-        # Second attempt
-        >> should_retry_pp_steps(provision_device_dry)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
-        # Third and last try
-        >> should_retry_pp_steps(provision_device_dry)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_device_dry)
+        >> pp_interaction(provision_device_dry)
+        >> pp_interaction(provision_device_dry)
+
         >> reset_pp_success_state
-        # First attempt at provisioning
-        >> should_retry_pp_steps(provision_device_real)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
-        # Second attempt
-        >> should_retry_pp_steps(provision_device_real)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
-        # Third and last try
-        >> should_retry_pp_steps(provision_device_real)
-        >> should_retry_pp_steps(await_pp_results)
-        >> should_retry_pp_steps(confirm_pp_results)
+        >> pp_interaction(provision_device_real)
+        >> pp_interaction(provision_device_real)
+        >> pp_interaction(provision_device_real)
+
         >> set_status(SubscriptionLifecycle.ACTIVE)
         >> resync
         >> done
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index 2a5a0b471a0096fcd0478e1cc5ccd3b25be5c781..f6602afd3d296a32aba3d44c33d29841e3e892ac 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -14,7 +14,7 @@ from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_types.device import Device
 from gso.products.product_types.iptrunk import IptrunkInactive, IptrunkProvisioning
 from gso.services import _ipam, provisioning_proxy
-from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results
+from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results, pp_interaction, reset_pp_success_state
 
 
 def initial_input_form_generator(product_name: str) -> FormGenerator:
@@ -245,30 +245,47 @@ def create_iptrunk() -> StepList:
         >> store_process_subscription(Target.CREATE)
         >> initialize_subscription
         >> get_info_from_ipam
-        >> 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_isis_iface_dry
-        >> await_pp_results
-        >> confirm_pp_results
-        >> provision_ip_trunk_isis_iface_real
-        >> await_pp_results
-        >> confirm_pp_results
-        >> provision_ip_trunk_ldp_iface_dry
-        >> await_pp_results
-        >> confirm_pp_results
-        >> provision_ip_trunk_ldp_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
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_iface_real)
+        >> pp_interaction(provision_ip_trunk_iface_real)
+        >> pp_interaction(provision_ip_trunk_iface_real)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_ldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_ldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_ldp_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_ldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_ldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_ldp_iface_real)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+
         >> set_status(SubscriptionLifecycle.ACTIVE)
         >> resync
         >> done
diff --git a/gso/workflows/iptrunk/modify_generic.py b/gso/workflows/iptrunk/modify_generic.py
index 8d813f18ab108b7bbc1e2bdfe245cf42c360ddc4..93400bca28a33c2fdb18369839d135d0daadde1a 100644
--- a/gso/workflows/iptrunk/modify_generic.py
+++ b/gso/workflows/iptrunk/modify_generic.py
@@ -12,7 +12,7 @@ from gso.products.product_blocks import PhyPortCapacity
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services import provisioning_proxy
-from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results
+from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results, reset_pp_success_state, pp_interaction
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -153,18 +153,27 @@ def modify_generic() -> StepList:
         >> 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
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+        >> pp_interaction(provision_ip_trunk_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_iface_real)
+        >> pp_interaction(provision_ip_trunk_iface_real)
+        >> pp_interaction(provision_ip_trunk_iface_real)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+        >> pp_interaction(provision_ip_trunk_lldp_iface_real)
+
         >> resync
         >> done
     )
diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py
index 18fafa55806b0837269460c8e0da11e6df92e747..afe007964c81dfe7b922e9111dfbbb4c51c94f42 100644
--- a/gso/workflows/iptrunk/modify_isis_metric.py
+++ b/gso/workflows/iptrunk/modify_isis_metric.py
@@ -7,7 +7,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services import provisioning_proxy
-from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results
+from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results, pp_interaction, reset_pp_success_state
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -71,12 +71,17 @@ def modify_isis_metric() -> StepList:
         >> store_process_subscription(Target.MODIFY)
         >> unsync
         >> modify_iptrunk_subscription
-        >> provision_ip_trunk_isis_iface_dry
-        >> await_pp_results
-        >> confirm_pp_results
-        >> provision_ip_trunk_isis_iface_real
-        >> await_pp_results
-        >> confirm_pp_results
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+        >> pp_interaction(provision_ip_trunk_isis_iface_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+        >> pp_interaction(provision_ip_trunk_isis_iface_real)
+
         >> resync
         >> done
     )
diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py
index 0388b7c7e3c116aaea497c779de0053460030866..dd6728df02946b08fdb6a43e5b99c9675f0053e0 100644
--- a/gso/workflows/iptrunk/terminate_iptrunk.py
+++ b/gso/workflows/iptrunk/terminate_iptrunk.py
@@ -12,7 +12,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services import ipam, provisioning_proxy
 from gso.services.ipam import V4ServiceNetwork, V6ServiceNetwork
-from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results
+from gso.services.provisioning_proxy import await_pp_results, confirm_pp_results, pp_interaction, reset_pp_success_state
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -92,15 +92,22 @@ def terminate_iptrunk() -> StepList:
         >> store_process_subscription(Target.TERMINATE)
         >> unsync
         >> modify_iptrunk_subscription
-        >> drain_traffic_from_ip_trunk
-        >> await_pp_results
-        >> confirm_pp_results
-        >> deprovision_ip_trunk_dry
-        >> await_pp_results
-        >> confirm_pp_results
-        >> deprovision_ip_trunk_real
-        >> await_pp_results
-        >> confirm_pp_results
+
+        >> reset_pp_success_state
+        >> pp_interaction(drain_traffic_from_ip_trunk)
+        >> pp_interaction(drain_traffic_from_ip_trunk)
+        >> pp_interaction(drain_traffic_from_ip_trunk)
+
+        >> reset_pp_success_state
+        >> pp_interaction(deprovision_ip_trunk_dry)
+        >> pp_interaction(deprovision_ip_trunk_dry)
+        >> pp_interaction(deprovision_ip_trunk_dry)
+
+        >> reset_pp_success_state
+        >> pp_interaction(deprovision_ip_trunk_real)
+        >> pp_interaction(deprovision_ip_trunk_real)
+        >> pp_interaction(deprovision_ip_trunk_real)
+
         >> deprovision_ip_trunk_ipv4
         >> deprovision_ip_trunk_ipv6
         >> set_status(SubscriptionLifecycle.TERMINATED)