diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
index 75882cf47a238bca9e67a1131829f75c20869ea2..7ebd7960d7db1239182b064aaa1b082a20bdbe41 100644
--- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
+++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
@@ -27,19 +27,19 @@
 #include <ArmarXCore/core/ArmarXManager.h>
 #include <ArmarXCore/core/ArmarXObjectScheduler.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
-#include <ArmarXCore/core/time/TimeUtil.h>
 #include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
 
 #include <RobotAPI/libraries/armem/core/error.h>
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
 #include <RobotAPI/libraries/armem_skills/aron_conversions.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 
 namespace armarx
 {
 
-    SkillsMemory::SkillsMemory():
+    SkillsMemory::SkillsMemory() :
         ReadWritePluginUser(),
         StatechartListenerComponentPluginUser(),
         SkillManagerComponentPluginUser(),
@@ -50,10 +50,11 @@ namespace armarx
     {
     }
 
-
-    armarx::PropertyDefinitionsPtr SkillsMemory::createPropertyDefinitions()
+    armarx::PropertyDefinitionsPtr
+    SkillsMemory::createPropertyDefinitions()
     {
-        armarx::PropertyDefinitionsPtr defs = new ComponentPropertyDefinitions(getConfigIdentifier());
+        armarx::PropertyDefinitionsPtr defs =
+            new ComponentPropertyDefinitions(getConfigIdentifier());
 
         const std::string prefix = "mem.";
         statechartListenerProviderSegment.defineProperties(defs, prefix + "statechartlistener.");
@@ -64,14 +65,14 @@ namespace armarx
         return defs;
     }
 
-
-    std::string SkillsMemory::getDefaultName() const
+    std::string
+    SkillsMemory::getDefaultName() const
     {
         return "SkillMemory";
     }
 
-
-    void SkillsMemory::onInitComponent()
+    void
+    SkillsMemory::onInitComponent()
     {
         statechartListenerProviderSegment.init();
         executableSkillCoreSegment.init();
@@ -79,24 +80,23 @@ namespace armarx
         skillEventCoreSegment.init();
     }
 
-
-    void SkillsMemory::onConnectComponent()
+    void
+    SkillsMemory::onConnectComponent()
     {
     }
 
-
-    void SkillsMemory::onDisconnectComponent()
+    void
+    SkillsMemory::onDisconnectComponent()
     {
-
     }
 
-
-    void SkillsMemory::onExitComponent()
+    void
+    SkillsMemory::onExitComponent()
     {
     }
 
-
-    armem::data::CommitResult SkillsMemory::commit(const armem::data::Commit& commit, const Ice::Current& current)
+    armem::data::CommitResult
+    SkillsMemory::commit(const armem::data::Commit& commit, const Ice::Current& current)
     {
         // This function is overloaded to check for skill executions
         // First pass arg to parent func to ensure that data is written into memory and that clients are notified
@@ -107,13 +107,15 @@ namespace armarx
 
         for (const auto& up : commit.updates)
         {
-            if (up.entityID.coreSegmentName == skills::segment::SkillExecutionRequestCoreSegment::CoreSegmentName)
+            if (up.entityID.coreSegmentName ==
+                skills::segment::SkillExecutionRequestCoreSegment::CoreSegmentName)
             {
                 for (const auto& instance : up.instancesData)
                 {
                     ARMARX_CHECK_NOT_NULL(instance);
 
-                    skills::manager::dto::SkillExecutionRequest exInfo = skillExecutionRequestCoreSegment.convertCommit(instance);
+                    skills::manager::dto::SkillExecutionRequest exInfo =
+                        skillExecutionRequestCoreSegment.convertCommit(instance);
                     SkillManagerComponentPluginUser::executeSkill(exInfo, current);
                 }
             }
@@ -122,7 +124,9 @@ namespace armarx
         return result;
     }
 
-    void SkillsMemory::addProvider(const skills::manager::dto::ProviderInfo& info, const Ice::Current &current)
+    void
+    SkillsMemory::addProvider(const skills::manager::dto::ProviderInfo& info,
+                              const Ice::Current& current)
     {
         SkillManagerComponentPluginUser::addProvider(info, current);
 
@@ -130,7 +134,8 @@ namespace armarx
         executableSkillCoreSegment.addSkillProvider(info);
     }
 
-    void SkillsMemory::removeProvider(const std::string& skillProviderName, const Ice::Current &current)
+    void
+    SkillsMemory::removeProvider(const std::string& skillProviderName, const Ice::Current& current)
     {
         executableSkillCoreSegment.removeSkillProvider(skillProviderName);
 
@@ -138,36 +143,52 @@ namespace armarx
         SkillManagerComponentPluginUser::removeProvider(skillProviderName, current);
     }
 
-    skills::provider::dto::SkillStatusUpdate SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current &current)
+    skills::manager::dto::SkillStatusUpdate
+    SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
+                               const Ice::Current& current)
     {
         skills::manager::dto::SkillExecutionRequest requestCopy = info;
         if (requestCopy.skillId.providerName == "*")
         {
             // sanitize the provider name if set to 'any'
-            requestCopy.skillId.providerName = getFirstProviderNameThatHasSkill(requestCopy.skillId.skillName);
+            requestCopy.skillId.providerName =
+                getFirstProviderNameThatHasSkill(requestCopy.skillId.skillName);
         }
 
         skillExecutionRequestCoreSegment.addSkillExecutionRequest(requestCopy);
         return SkillManagerComponentPluginUser::executeSkill(requestCopy, current);
     }
 
-    void SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, const Ice::Current &current)
+    void
+    SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
+                                       const std::string& providerName,
+                                       const Ice::Current& current)
     {
-        skillEventCoreSegment.addSkillUpdateEvent(update);
+        skillEventCoreSegment.addSkillUpdateEvent(update, providerName);
     }
 
-
+    skills::provider::dto::SkillStatusUpdateList
+    SkillsMemory::getLatestSkillExecutionStatuses(int n, const Ice::Current& current)
+    {
+        return {};
+    }
 
     /*
      * Statechart stuff
      */
-    void SkillsMemory::reportStatechartTransitionWithParameters(const ProfilerStatechartTransitionWithParameters& x, const Ice::Current&)
+    void
+    SkillsMemory::reportStatechartTransitionWithParameters(
+        const ProfilerStatechartTransitionWithParameters& x,
+        const Ice::Current&)
     {
         statechartListenerProviderSegment.reportStatechartTransitionWithParameters(x);
     }
 
-    void SkillsMemory::reportStatechartTransitionWithParametersList(const ProfilerStatechartTransitionWithParametersList& x, const Ice::Current&)
+    void
+    SkillsMemory::reportStatechartTransitionWithParametersList(
+        const ProfilerStatechartTransitionWithParametersList& x,
+        const Ice::Current&)
     {
         statechartListenerProviderSegment.reportStatechartTransitionWithParametersList(x);
     }
-}
+} // namespace armarx
diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
index 91506c16fb87793083328d173d973f19ad268e75..d0b92b485024b7c80ab11b52d4ff28b9893aca23 100644
--- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
+++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
@@ -30,16 +30,14 @@
 #include <ArmarXCore/observers/ObserverObjectFactories.h>
 
 #include <RobotAPI/interface/skills/SkillMemoryInterface.h>
-
-#include <RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h>
-#include <RobotAPI/libraries/armem_skills/server/StatechartListenerComponentPlugin.h>
 #include <RobotAPI/libraries/armem/server/plugins/ReadWritePluginUser.h>
-
 #include <RobotAPI/libraries/armem_skills/aron/Statechart.aron.generated.h>
-#include <RobotAPI/libraries/armem_skills/server/segment/StatechartListenerSegment.h>
+#include <RobotAPI/libraries/armem_skills/server/StatechartListenerComponentPlugin.h>
 #include <RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.h>
-#include <RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h>
 #include <RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h>
+#include <RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h>
+#include <RobotAPI/libraries/armem_skills/server/segment/StatechartListenerSegment.h>
+#include <RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h>
 
 namespace armarx
 {
@@ -63,27 +61,37 @@ namespace armarx
         virtual public SkillManagerComponentPluginUser
     {
     public:
-
         SkillsMemory();
 
         /// @see armarx::ManagedIceObject::getDefaultName()
         std::string getDefaultName() const override;
 
         // Override StatechartListener
-        void reportStatechartTransitionWithParameters(const ProfilerStatechartTransitionWithParameters&, const Ice::Current&) override;
-        void reportStatechartTransitionWithParametersList(const ProfilerStatechartTransitionWithParametersList&, const Ice::Current&) override;
+        void
+        reportStatechartTransitionWithParameters(const ProfilerStatechartTransitionWithParameters&,
+                                                 const Ice::Current&) override;
+        void reportStatechartTransitionWithParametersList(
+            const ProfilerStatechartTransitionWithParametersList&,
+            const Ice::Current&) override;
 
         // Override SkillManager to add memory functions
-        void addProvider(const skills::manager::dto::ProviderInfo& info, const Ice::Current &current) override;
-        void removeProvider(const std::string&, const Ice::Current &current) override;
-        skills::provider::dto::SkillStatusUpdate executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current &current) override;
-        void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& statusUpdate, const Ice::Current &current) override;
+        void addProvider(const skills::manager::dto::ProviderInfo& info,
+                         const Ice::Current& current) override;
+        void removeProvider(const std::string&, const Ice::Current& current) override;
+        skills::manager::dto::SkillStatusUpdate
+        executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
+                     const Ice::Current& current) override;
+        void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& statusUpdate,
+                                  const std::string& providerName,
+                                  const Ice::Current& current) override;
+        skills::provider::dto::SkillStatusUpdateList
+        getLatestSkillExecutionStatuses(int n, const Ice::Current& current) override;
 
         // WritingInterface interface
-        armem::data::CommitResult commit(const armem::data::Commit& commit, const Ice::Current&) override;
+        armem::data::CommitResult commit(const armem::data::Commit& commit,
+                                         const Ice::Current&) override;
 
     protected:
-
         /// @see armarx::ManagedIceObject::onInitComponent()
         void onInitComponent() override;
 
@@ -101,12 +109,12 @@ namespace armarx
 
 
     private:
-
         static constexpr const char* MemoryName = "Skill";
 
         struct Properties
         {
         };
+
         Properties p;
 
         skills::segment::StatechartListenerProviderSegment statechartListenerProviderSegment;
@@ -114,4 +122,4 @@ namespace armarx
         skills::segment::SkillEventCoreSegment skillEventCoreSegment;
         skills::segment::SkillExecutionRequestCoreSegment skillExecutionRequestCoreSegment;
     };
-}
+} // namespace armarx
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui
index 7c25a1b848daab3347a7247199aa9a54eefb99bc..70005fd88479a409694b7da6db3a806369f2fc50 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui
@@ -20,8 +20,38 @@
    <string>SkillManagerMonitorWidget</string>
   </property>
   <layout class="QGridLayout" name="gridLayout_3">
-   <item row="0" column="0">
+   <item row="3" column="0">
+    <widget class="QCheckBox" name="autoUpdateCheckBox">
+     <property name="text">
+      <string>Auto Update</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="3">
+    <widget class="QPushButton" name="refreshNowPushButton">
+     <property name="text">
+      <string>Refresh Now</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="2">
+    <widget class="QDoubleSpinBox" name="doubleSpinBoxUpdateFreq"/>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Update Frequency:</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="4">
     <widget class="QSplitter" name="splitter_2">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
      <property name="sizePolicy">
       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
        <horstretch>0</horstretch>
@@ -34,25 +64,49 @@
      <property name="childrenCollapsible">
       <bool>false</bool>
      </property>
-     <widget class="QGroupBox" name="groupBoxActiveSkills">
+     <widget class="QGroupBox" name="groupBoxSkillExecutions">
       <property name="sizePolicy">
-       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="title">
-       <string>Active Skills</string>
+       <string>Executions</string>
       </property>
       <layout class="QGridLayout" name="gridLayout_4">
-       <item row="0" column="0">
-        <widget class="QListWidget" name="listWidgetActiveSkills">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
+       <item row="1" column="0" colspan="3">
+        <widget class="QTreeWidget" name="treeWidget">
+         <column>
+          <property name="text">
+           <string>ID</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Skill</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Scheduled</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Started</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Finished</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Executor</string>
+          </property>
+         </column>
         </widget>
        </item>
       </layout>
@@ -78,16 +132,6 @@
         <string>Manager</string>
        </property>
        <layout class="QGridLayout" name="gridLayout">
-        <item row="3" column="1">
-         <widget class="QDoubleSpinBox" name="doubleSpinBoxUpdateFreq"/>
-        </item>
-        <item row="3" column="0">
-         <widget class="QLabel" name="label">
-          <property name="text">
-           <string>Update Frequency:</string>
-          </property>
-         </widget>
-        </item>
         <item row="4" column="0" colspan="3">
          <widget class="QTreeWidget" name="treeWidgetSkills">
           <column>
@@ -100,30 +144,14 @@
             <string>HasType</string>
            </property>
           </column>
-          <column>
-           <property name="text">
-            <string>State</string>
-           </property>
-          </column>
-         </widget>
-        </item>
-        <item row="2" column="0">
-         <widget class="QCheckBox" name="autoUpdateCheckBox">
-          <property name="text">
-           <string>Auto Update</string>
-          </property>
-         </widget>
-        </item>
-        <item row="2" column="2">
-         <widget class="QPushButton" name="refreshNowPushButton">
-          <property name="text">
-           <string>Refresh Now</string>
-          </property>
          </widget>
         </item>
        </layout>
       </widget>
       <widget class="QGroupBox" name="groupBoxSkillDetails">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
          <horstretch>0</horstretch>
@@ -134,7 +162,35 @@
         <string>Skill Details</string>
        </property>
        <layout class="QGridLayout" name="gridLayout_2">
-        <item row="1" column="0" colspan="4">
+        <item row="8" column="3">
+         <widget class="QPushButton" name="pushButtonExecuteSkill">
+          <property name="text">
+           <string>Request Execution</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="0">
+         <widget class="QPushButton" name="pushButtonPaste">
+          <property name="text">
+           <string>Set args from clipboard</string>
+          </property>
+         </widget>
+        </item>
+        <item row="8" column="0">
+         <widget class="QPushButton" name="pushButtonStopSkill">
+          <property name="text">
+           <string>Stop current skill</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="3">
+         <widget class="QPushButton" name="pushButtonReset">
+          <property name="text">
+           <string>Reset args</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="0" colspan="4">
          <widget class="QTreeWidget" name="treeWidgetSkillDetails">
           <property name="contextMenuPolicy">
            <enum>Qt::CustomContextMenu</enum>
@@ -164,34 +220,6 @@
           </column>
          </widget>
         </item>
-        <item row="6" column="3">
-         <widget class="QPushButton" name="pushButtonExecuteSkill">
-          <property name="text">
-           <string>Request Execution</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="0">
-         <widget class="QPushButton" name="pushButtonPaste">
-          <property name="text">
-           <string>Set from clipboard</string>
-          </property>
-         </widget>
-        </item>
-        <item row="6" column="0">
-         <widget class="QPushButton" name="pushButtonStopSkill">
-          <property name="text">
-           <string>Stop current skill</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="3">
-         <widget class="QPushButton" name="pushButtonReset">
-          <property name="text">
-           <string>Reset args</string>
-          </property>
-         </widget>
-        </item>
         <item row="0" column="1">
          <widget class="QPushButton" name="pushButtonCopy">
           <property name="text">
@@ -199,6 +227,15 @@
           </property>
          </widget>
         </item>
+        <item row="1" column="1" colspan="3">
+         <widget class="QComboBox" name="profileComboBox">
+          <item>
+           <property name="text">
+            <string>&lt;No Profile&gt;</string>
+           </property>
+          </item>
+         </widget>
+        </item>
        </layout>
       </widget>
      </widget>
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
index c3dcb38aa24acad06a66c0aab7ee5691d25fa541..70fdd6812a03738a728f2e4e06c099217e6cb8c3 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
@@ -82,14 +82,15 @@ namespace armarx
     {
         widget.setupUi(getWidget());
 
-        widget.doubleSpinBoxUpdateFreq->setValue(5.0);
-        widget.doubleSpinBoxUpdateFreq->setMinimum(0);
-        widget.doubleSpinBoxUpdateFreq->setMaximum(100);
+        double default_hz = 2;
+        widget.doubleSpinBoxUpdateFreq->setValue(default_hz);
+        widget.doubleSpinBoxUpdateFreq->setMinimum(0.5);
+        widget.doubleSpinBoxUpdateFreq->setMaximum(20);
         widget.doubleSpinBoxUpdateFreq->setSingleStep(0.5);
         widget.doubleSpinBoxUpdateFreq->setSuffix(" Hz");
 
         refreshSkillsResultTimer = new QTimer(this);
-        refreshSkillsResultTimer->setInterval(1000 / 2); // Keep this stable.
+        updateTimerFrequency();
         refreshSkillsResultTimer->start();
 
         connect(widget.doubleSpinBoxUpdateFreq,
@@ -99,7 +100,7 @@ namespace armarx
         connect(refreshSkillsResultTimer,
                 &QTimer::timeout,
                 this,
-                &SkillManagerMonitorWidgetController::refreshSkillsPeriodically);
+                &SkillManagerMonitorWidgetController::refreshSkillsAndExecutions);
 
         connect(widget.pushButtonCopy,
                 &QPushButton::clicked,
@@ -175,28 +176,21 @@ namespace armarx
     }
 
     void
-    SkillManagerMonitorWidgetController::refreshSkillsPeriodically()
+    SkillManagerMonitorWidgetController::refreshSkillsAndExecutions()
     {
         if (widget.autoUpdateCheckBox->isChecked())
         {
             refreshSkills();
+            refreshExecutions();
         }
     }
 
     void
     SkillManagerMonitorWidgetController::refreshSkills()
     {
-        static std::map<skills::provider::dto::Execution::Status, std::string>
-            ExecutionStatus2String = {
-                {skills::provider::dto::Execution::Status::Aborted, "Aborted"},
-                {skills::provider::dto::Execution::Status::Failed, "Failed"},
-                {skills::provider::dto::Execution::Status::Idle, "Not yet started"},
-                {skills::provider::dto::Execution::Status::Running, "Running"},
-                {skills::provider::dto::Execution::Status::Scheduled, "Scheduled"},
-                {skills::provider::dto::Execution::Status::Succeeded, "Succeeded"}};
-
         if (!manager)
         {
+            // check if null
             return;
         }
 
@@ -204,9 +198,10 @@ namespace armarx
         // remove non-existing ones
         try
         {
-            ARMARX_DEBUG << "GET REMOVED PROVIDERS AND REMOVE FROM MAP";
-            std::scoped_lock l(skillMutex);
+            std::scoped_lock l(updateMutex);
+
             auto managerSkills = manager->getSkillDescriptions();
+
             std::vector<std::string> removedProviders;
             for (auto it = skills.begin(); it != skills.end();)
             {
@@ -225,21 +220,18 @@ namespace armarx
             }
 
             // add new ones
-            ARMARX_DEBUG << "GET NEW PROVIDERS AND ADD THEM TO MAP";
             std::vector<std::string> newProviders;
             for (const auto& [providerName, providerSkills] : managerSkills)
             {
                 if (skills.find(providerName) == skills.end())
                 {
-                    ARMARX_DEBUG << "ADD " << providerName;
                     skills.insert(std::make_pair(providerName, providerSkills));
                     newProviders.push_back(providerName);
                 }
             }
 
-            /* CHECK TREE VIEW */
+            /* UPDATE TREE VIEW */
             // remove providers from tree
-            ARMARX_DEBUG << "REMOVE PROVIDERS FROM TREE VIEW";
             int i = 0;
             while (i < widget.treeWidgetSkills->topLevelItemCount())
             {
@@ -249,7 +241,6 @@ namespace armarx
                                         item->text(0).toStdString());
                     it != removedProviders.end())
                 {
-                    ARMARX_DEBUG << "REMOVE PROVIDER " << *it;
                     delete widget.treeWidgetSkills->takeTopLevelItem(i);
                 }
                 else
@@ -259,7 +250,6 @@ namespace armarx
             }
 
             // add new providers
-            ARMARX_DEBUG << "ADD NEW PROVIDERS TO TREE VIEW";
             for (const auto& [providerName, providerSkills] : skills)
             {
                 if (auto it = std::find(newProviders.begin(), newProviders.end(), providerName);
@@ -269,87 +259,105 @@ namespace armarx
                     item->setText(0, QString::fromStdString(providerName));
                     for (const auto& [name, sk] : providerSkills)
                     {
-                        ARMARX_DEBUG << "ADD PROVIDER " << *it;
                         auto itsk = new QTreeWidgetItem(item);
                         item->addChild(itsk);
                         itsk->setText(0, QString::fromStdString(name));
                     }
                 }
             }
+        }
+        catch (...)
+        {
+            // perhaps the manager died during the method?
+        }
+    }
 
-            // update status and active skills window
-            ARMARX_DEBUG << "UPDATE STATI AND ACTIVE SKILL";
-            std::map<skills::SkillID, std::string> activeSkillsAndPrefixes;
-            auto managerStatuses = manager->getSkillExecutionStatuses();
-            for (int i = 0; i < widget.treeWidgetSkills->topLevelItemCount(); ++i)
-            {
-                try
-                {
-                    QTreeWidgetItem* item = widget.treeWidgetSkills->topLevelItem(i);
-                    auto providerName = item->text(0).toStdString();
-
-                    ARMARX_DEBUG << "UPDATE STATI FOR PROVIDER " << providerName;
-                    auto allStatusesForProvider = managerStatuses.at(providerName);
-
-                    for (int j = 0; j < item->childCount(); ++j)
-                    {
-                        QTreeWidgetItem* skillItem = item->child(j);
-                        skills::SkillID currentSkillId(providerName,
-                                                       skillItem->text(0).toStdString());
-
-                        ARMARX_DEBUG << "UPDATE STATI FOR SKILL " << currentSkillId.skillName;
-                        auto statusForSkill = allStatusesForProvider.at(currentSkillId.skillName);
-                        skillItem->setText(2,
-                                           QString::fromStdString(ExecutionStatus2String.at(
-                                               statusForSkill.header.status)));
-
-                        if (not statusForSkill.header.executorName
-                                    .empty()) // it means that the skill was called by someone
-                        {
-                            ARMARX_DEBUG << "ADD SKILL TO ACTIVE " << currentSkillId.skillName;
-                            activeSkillsAndPrefixes.insert(
-                                {currentSkillId, statusForSkill.header.executorName});
-                        }
-                    }
-                }
-                catch (...)
-                {
-                    // Perhaps the skill provider died after the check at the beginning of this method
-                    continue;
-                }
-            }
+    void
+    SkillManagerMonitorWidgetController::refreshExecutions()
+    {
+        static std::map<skills::provider::dto::Execution::Status, std::string>
+            ExecutionStatus2String = {
+                // Terminating
+                {skills::provider::dto::Execution::Status::Aborted, "Aborted"},
+                {skills::provider::dto::Execution::Status::Failed, "Failed"},
+                {skills::provider::dto::Execution::Status::Succeeded, "Succeeded"},
 
-            // finally update the view of active skills
-            ARMARX_DEBUG << "UPDATE ACTIVE SKILLS";
-            widget.listWidgetActiveSkills->clear();
-            for (const auto& [id, prefix] : activeSkillsAndPrefixes)
-            {
-                auto prefixedStr = id.toString(prefix);
-                bool longest = true;
-                for (
-                    const auto& [id2, prefix2] :
-                    activeSkillsAndPrefixes) // check if there is a deeper skill currently executing
-                {
-                    auto prefixedStr2 = id.toString(prefix2);
-                    if (prefixedStr == prefixedStr2)
-                    {
-                        continue;
-                    }
+                // Others
+                {skills::provider::dto::Execution::Status::Idle, "Not yet started"},
+                {skills::provider::dto::Execution::Status::Running, "Running"},
+                {skills::provider::dto::Execution::Status::Scheduled, "Scheduled"}};
 
-                    if (simox::alg::starts_with(prefixedStr2, prefixedStr))
-                    {
-                        longest = false;
-                        break;
-                    }
-                }
+        if (!manager)
+        {
+            // check if null
+            return;
+        }
 
-                if (longest)
-                {
-                    widget.listWidgetActiveSkills->addItem(
-                        QString::fromStdString(id.toString() + ": " + id.toString(prefix)));
-                }
-            }
+        try
+        {
+            //            std::scoped_lock l(updateMutex);
+
+            //            auto managerStatuses = manager->getSkillExecutionStatuses();
+
+            //            // update status and active skills window
+            //            std::map<skills::SkillID, std::string> activeSkillsAndPrefixes;
+            //            for (int i = 0; i < widget.treeWidgetSkills->topLevelItemCount(); ++i)
+            //            {
+            //                QTreeWidgetItem* item = widget.treeWidgetSkills->topLevelItem(i);
+            //                auto providerName = item->text(0).toStdString();
+
+
+            //                auto allStatusesForProvider = managerStatuses.at(providerName);
+
+            //                for (int j = 0; j < item->childCount(); ++j)
+            //                {
+            //                    QTreeWidgetItem* skillItem = item->child(j);
+            //                    skills::SkillID currentSkillId(providerName, skillItem->text(0).toStdString());
+
+            //                    auto statusForSkill = allStatusesForProvider.at(currentSkillId.skillName);
+            //                    skillItem->setText(2,
+            //                                       QString::fromStdString(ExecutionStatus2String.at(
+            //                                           statusForSkill.header.status)));
+
+            //                    if (not statusForSkill.header.executorName
+            //                                .empty()) // it means that the skill was called by someone
+            //                    {
+            //                        activeSkillsAndPrefixes.insert(
+            //                            {currentSkillId, statusForSkill.header.executorName});
+            //                    }
+            //                }
+            //            }
+
+            //            widget.listWidgetActiveSkills->clear();
+            //            for (const auto& [id, prefix] : activeSkillsAndPrefixes)
+            //            {
+            //                auto prefixedStr = id.toString(prefix);
+            //                bool longest = true;
+            //                for (
+            //                    const auto& [id2, prefix2] :
+            //                    activeSkillsAndPrefixes) // check if there is a deeper skill currently executing
+            //                {
+            //                    auto prefixedStr2 = id.toString(prefix2);
+            //                    if (prefixedStr == prefixedStr2)
+            //                    {
+            //                        continue;
+            //                    }
+
+            //                    if (simox::alg::starts_with(prefixedStr2, prefixedStr))
+            //                    {
+            //                        longest = false;
+            //                        break;
+            //                    }
+            //                }
+
+            //                if (longest)
+            //                {
+            //                    widget.listWidgetActiveSkills->addItem(
+            //                        QString::fromStdString(id.toString() + ": " + id.toString(prefix)));
+            //                }
+            //            }
         }
+
         catch (...)
         {
             // perhaps the manager died during the method?
@@ -364,7 +372,7 @@ namespace armarx
             return;
         }
 
-        std::scoped_lock l(skillMutex);
+        std::scoped_lock l(updateMutex);
         const auto& skillDescriptions = skills.at(selectedSkill.providerName);
         if (!skillDescriptions.count(selectedSkill.skillName))
         {
@@ -391,7 +399,7 @@ namespace armarx
     void
     SkillManagerMonitorWidgetController::stopSkill()
     {
-        std::scoped_lock l(skillMutex);
+        std::scoped_lock l(updateMutex);
         if (selectedSkill.providerName.empty() or selectedSkill.skillName.empty())
         {
             return;
@@ -412,7 +420,7 @@ namespace armarx
     SkillManagerMonitorWidgetController::skillSelectionChanged(QTreeWidgetItem* current,
                                                                QTreeWidgetItem*)
     {
-        std::scoped_lock l(skillMutex);
+        std::scoped_lock l(updateMutex);
         widget.groupBoxSkillDetails->setEnabled(false);
 
         if (!current)
@@ -487,7 +495,7 @@ namespace armarx
                                                             {QString::fromStdString("Arguments")});
         auto aron_args = aron::type::Object::FromAronObjectDTO(skillDesc.acceptedType);
         auto default_args =
-            nullptr; //aron::data::Dict::FromAronDictDTO(skillDesc.defaultParams); TODO!
+            nullptr; //aron::data::Dict::FromAronDictDTO(skillDesc.defaultParams); TODO! fabian.peller
 
         aronTreeWidgetController = std::make_shared<AronTreeWidgetController>(
             widget.treeWidgetSkillDetails, skillsArgumentsTreeWidgetItem, aron_args, default_args);
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
index f1ad1bb720ea69503b86b00f75a6e6f09f6058c5..d6e93d9787b80908932dd8d02bf2a33177aaaf90 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
@@ -81,7 +81,8 @@ namespace armarx
 
         void updateTimerFrequency();
         void refreshSkills();
-        void refreshSkillsPeriodically();
+        void refreshExecutions();
+        void refreshSkillsAndExecutions();
 
         void copyCurrentConfig();
         void pasteCurrentConfig();
@@ -108,7 +109,7 @@ namespace armarx
         };
 
         // Data taken from observer (snapshot of it)
-        mutable std::mutex skillMutex;
+        mutable std::mutex updateMutex;
         skills::manager::dto::SkillDescriptionMapMap skills = {};
 
         // User Input
diff --git a/source/RobotAPI/interface/skills/SkillManagerInterface.ice b/source/RobotAPI/interface/skills/SkillManagerInterface.ice
index 088d28561684e1a604595f63af4aad6903e4caaf..17a07d8bcdf22678a551c56bf4b17a97c939532c 100644
--- a/source/RobotAPI/interface/skills/SkillManagerInterface.ice
+++ b/source/RobotAPI/interface/skills/SkillManagerInterface.ice
@@ -32,13 +32,52 @@ module armarx
         {
             module dto
             {
-                // Inputs
+                // A skill ID. Must be unique within one SkillManager
+                struct SkillID
+                {
+                    string providerName;
+                    string skillName;
+                };
+
+                // The minimum information that is needed to uniquely identifying a past skill execution
+                struct SkillExecutionID
+                {
+                    SkillID skillId; // the id of the skill
+                    string
+                        executorName; // the name of the component/lib/skill that called the execution of the skill
+                    armarx::core::time::dto::DateTime
+                        executionStartedTime; // The time a skill was triggered
+                };
+
+                // Status updates of a skill (similar to the status update of the providers except the skillID)
+                struct SkillStatusUpdateHeader
+                {
+                    SkillExecutionID executionId;
+                    aron::data::dto::Dict usedParams; // the used parameterization
+                    callback::dti::SkillProviderCallbackInterface*
+                        usedCallbackInterface; // the used callback interface. Probably a prx to the manager
+                    provider::dto::Execution::Status status; // the current status of the skill
+                };
+
+                // (similar to the status update of the providers except the skillID)
+                struct SkillStatusUpdate
+                {
+                    SkillStatusUpdateHeader header;
+                    aron::data::dto::Dict
+                        data; // data, attached to the status update. If send via a callback, this data may be used by the callback interface
+                };
+
+                sequence<SkillStatusUpdate> SkillStatusUpdateList;
+
                 struct SkillExecutionRequest
                 {
+                    SkillID
+                        skillId; // The id of a skill to request. Note that the skill or provider name can be regexes.
                     string executorName; // Who called the request
-                    provider::dto::SkillID skillId; // The id of a skill to request. Note that the skill or provider name can be regexes.
-                    aron::data::dto::Dict params; // the parameters for the skill. Can be nullptr if the skill does not require parameters
+                    aron::data::dto::Dict
+                        params; // the parameters for the skill. Can be nullptr if the skill does not require parameters
                 };
+
                 struct ProviderInfo
                 {
                     string providerName;
@@ -48,24 +87,32 @@ module armarx
 
                 // Provider data types
                 dictionary<string, provider::dto::SkillDescriptionMap> SkillDescriptionMapMap;
-                dictionary<string, provider::dto::SkillStatusUpdateMap> SkillStatusUpdateMapMap;
             }
 
             module dti
             {
-                interface SkillManagerInterface extends callback::dti::SkillProviderCallbackInterface
+                interface SkillManagerInterface extends
+                    callback::dti::SkillProviderCallbackInterface
                 {
-                    // There is by design no method to get the ProviderInfo. You should only communicate with the manager
+                    // !! There is by design no method to get the ProviderInfo. You should only communicate with the manager !!
 
                     void addProvider(dto::ProviderInfo providerInfo);
+
                     void removeProvider(string providerName);
 
-                    dto::SkillDescriptionMapMap getSkillDescriptions();
-                    dto::SkillStatusUpdateMapMap getSkillExecutionStatuses();
+                    dto::SkillDescriptionMapMap
+                    getSkillDescriptions(); // get all skilldescriptions from all providers
 
-                    provider::dto::SkillStatusUpdate executeSkill(dto::SkillExecutionRequest skillExecutionInfo);
-                    void abortSkill(string providerName, string skillName);
+                    dto::SkillStatusUpdate
+                    getSkillExecutionStatus(dto::SkillExecutionID executionId);
+
+                    dto::SkillStatusUpdateList
+                    getSkillExecutionStatuses(); // returns the current executions from all providers
 
+                    dto::SkillStatusUpdate
+                    executeSkill(dto::SkillExecutionRequest skillExecutionInfo);
+
+                    void abortSkill(string providerName, string skillName);
                 };
             }
         }
diff --git a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
index c8e3212efa1b0ae3bf2768a124a53441898cd6de..09e5db8712062f63759c11d92bc66d6af5875470 100644
--- a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
+++ b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
@@ -24,10 +24,10 @@
 
 #include <ArmarXCore/interface/core/Profiler.ice>
 
-#include <RobotAPI/interface/skills/SkillProviderInterface.ice>
+#include <RobotAPI/interface/armem/server/MemoryInterface.ice>
 #include <RobotAPI/interface/skills/SkillManagerInterface.ice>
+#include <RobotAPI/interface/skills/SkillProviderInterface.ice>
 #include <RobotAPI/interface/skills/StatechartListenerInterface.ice>
-#include <RobotAPI/interface/armem/server/MemoryInterface.ice>
 
 module armarx
 {
@@ -35,8 +35,11 @@ module armarx
     {
         module dti
         {
-            interface SkillMemoryInterface extends armem::server::MemoryInterface, dti::StatechartListenerInterface, manager::dti::SkillManagerInterface
+            interface SkillMemoryInterface extends armem::server::MemoryInterface,
+                dti::StatechartListenerInterface, manager::dti::SkillManagerInterface
             {
+                provider::dto::SkillStatusUpdateList getLatestSkillExecutionStatuses(
+                    int n); // returns latest n statusupdates of all providers
             };
         }
     }
diff --git a/source/RobotAPI/interface/skills/SkillProviderInterface.ice b/source/RobotAPI/interface/skills/SkillProviderInterface.ice
index b7aad029ed84a8918fd68c7fda76fc325e2c6241..300054875b5948ba23a75563928e9b7cd55237d6 100644
--- a/source/RobotAPI/interface/skills/SkillProviderInterface.ice
+++ b/source/RobotAPI/interface/skills/SkillProviderInterface.ice
@@ -22,6 +22,8 @@
 
 #pragma once
 
+#include <ArmarXCore/interface/core/time.ice>
+
 #include <RobotAPI/interface/aron.ice>
 
 
@@ -51,13 +53,6 @@ module armarx
             {
                 sequence<string> StringList;
 
-                // A skill ID. Must be unique within one SkillManager
-                struct SkillID
-                {
-                    string providerName;
-                    string skillName;
-                };
-
                 // A parameterization profile
                 struct SkillProfile
                 {
@@ -100,23 +95,31 @@ module armarx
                 {
                     enum Status
                     {
-                        Idle, // a skill can only be idled if it has never been scheduled
+                        Idle,
                         Scheduled,
                         Running,
 
-                        // terminating values
+                        // terminating values, after execution a skill goes back to idle
                         Failed,
                         Succeeded,
                         Aborted
                     };
                 }
 
-                // Status updates of a skill
-                struct SkillStatusUpdateHeader
+                // The minimum information that is needed to uniquely identifying a past skill execution
+                struct SkillExecutionID
                 {
-                    SkillID skillId; // the id of the skill
+                    string skillName; // the name of the skill
                     string
                         executorName; // the name of the component/lib/skill that called the execution of the skill
+                    armarx::core::time::dto::DateTime
+                        executionStartedTime; // The time a skill was triggered
+                };
+
+                // Status updates of a skill
+                struct SkillStatusUpdateHeader
+                {
+                    SkillExecutionID executionId;
                     aron::data::dto::Dict usedParams; // the used parameterization
                     callback::dti::SkillProviderCallbackInterface*
                         usedCallbackInterface; // the used callback interface. Probably a prx to the manager
@@ -130,7 +133,7 @@ module armarx
                         data; // data, attached to the status update. If send via a callback, this data may be used by the callback interface
                 };
 
-                dictionary<string, SkillStatusUpdate> SkillStatusUpdateMap;
+                sequence<SkillStatusUpdate> SkillStatusUpdateList;
             }
 
             module dti
@@ -139,8 +142,10 @@ module armarx
                 {
                     dto::SkillDescription getSkillDescription(string name);
                     dto::SkillDescriptionMap getSkillDescriptions();
-                    dto::SkillStatusUpdate getSkillExecutionStatus(string name);
-                    dto::SkillStatusUpdateMap getSkillExecutionStatuses();
+                    dto::SkillStatusUpdate
+                    getSkillExecutionStatus(dto::SkillExecutionID executionId);
+                    dto::SkillStatusUpdateList
+                    getSkillExecutionStatuses(); // returns all current skill executions chronologically
 
                     // execute skill will ALWAYS fully execute the skill and wait, until the skill is finished.
                     // Use the _begin() method, if you want to call a skill async
@@ -167,7 +172,8 @@ module armarx
                 interface SkillProviderCallbackInterface
                 {
                     // used for callbacks from providers to update their skill execution status
-                    void updateStatusForSkill(provider::dto::SkillStatusUpdate statusUpdate);
+                    void updateStatusForSkill(provider::dto::SkillStatusUpdate statusUpdate,
+                                              string providerName);
                 }
             }
         }
diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
index 1fa0989e8938206462674f93d9646f48b065123f..8eb81c1647460d19e6a09ece3bd2acaa6551afd8 100644
--- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
+++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
@@ -1,49 +1,58 @@
 #include "SkillEventSegment.h"
 
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 #include <SimoxUtility/algorithm/string.h>
 
-#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
-
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h>
+#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
+#include <RobotAPI/libraries/skills/provider/SkillStatusUpdate.h>
 
 namespace armarx::skills::segment
 {
 
-    SkillEventCoreSegment::SkillEventCoreSegment(armem::server::MemoryToIceAdapter& iceMemory):
-        Base(iceMemory, CoreSegmentName, armarx::skills::arondto::SkillExecutionRequest::ToAronType())
+    SkillEventCoreSegment::SkillEventCoreSegment(armem::server::MemoryToIceAdapter& iceMemory) :
+        Base(iceMemory,
+             CoreSegmentName,
+             armarx::skills::arondto::SkillExecutionRequest::ToAronType())
     {
     }
 
-    void SkillEventCoreSegment::defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix)
+    void
+    SkillEventCoreSegment::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix)
     {
         // No properties! (meaning no name and no max size)
     }
 
-    void SkillEventCoreSegment::init()
+    void
+    SkillEventCoreSegment::init()
     {
         Base::init();
     }
 
-    void SkillEventCoreSegment::addSkillUpdateEvent(const skills::provider::dto::SkillStatusUpdate& update)
+    void
+    SkillEventCoreSegment::addSkillUpdateEvent(
+        const skills::provider::dto::SkillStatusUpdate& update,
+        const std::string& providerName)
     {
         // add update for skill to memory
-        static std::map<armarx::skills::provider::dto::Execution::Status, std::string> ExecutionStatus2String = {
-            {armarx::skills::provider::dto::Execution::Status::Idle, "Idle"},
-            {armarx::skills::provider::dto::Execution::Status::Scheduled, "Scheduled"},
-            {armarx::skills::provider::dto::Execution::Status::Running, "Running"},
-            {armarx::skills::provider::dto::Execution::Status::Aborted, "Aborted"},
-            {armarx::skills::provider::dto::Execution::Status::Failed, "Failed"},
-            {armarx::skills::provider::dto::Execution::Status::Succeeded, "Succeeded"}
-        };
+        static std::map<armarx::skills::provider::dto::Execution::Status, std::string>
+            ExecutionStatus2String = {
+                {armarx::skills::provider::dto::Execution::Status::Idle, "Idle"},
+                {armarx::skills::provider::dto::Execution::Status::Scheduled, "Scheduled"},
+                {armarx::skills::provider::dto::Execution::Status::Running, "Running"},
+                {armarx::skills::provider::dto::Execution::Status::Aborted, "Aborted"},
+                {armarx::skills::provider::dto::Execution::Status::Failed, "Failed"},
+                {armarx::skills::provider::dto::Execution::Status::Succeeded, "Succeeded"}};
+
+        auto up = skills::SkillStatusUpdate::FromIce(update, providerName);
 
         // create commit about new update
         armarx::skills::arondto::SkillExecutionEvent event;
-        event.providerName = update.header.skillId.providerName;
-        event.skillName = update.header.skillId.skillName;
+        event.providerName = up.executionId.skillId.providerName;
+        event.skillName = up.executionId.skillId.skillName;
         event.status = ExecutionStatus2String.at(update.header.status);
-        event.params = aron::data::Dict::FromAronDictDTO(update.header.usedParams);
-        event.data = aron::data::Dict::FromAronDictDTO(update.data);
+        event.params = up.usedParameterization.usedInputParams;
+        event.data = up.data;
 
         armem::MemoryID commitId = id();
         commitId.providerSegmentName = event.providerName;
@@ -55,9 +64,9 @@ namespace armarx::skills::segment
         auto& entityUpdate = comm.add();
         entityUpdate.confidence = 1.0;
         entityUpdate.referencedTime = armem::Time::Now();
-        entityUpdate.instancesData = { aron };
+        entityUpdate.instancesData = {aron};
         entityUpdate.entityID = commitId;
 
         iceMemory.commit(comm);
     }
-}
+} // namespace armarx::skills::segment
diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h
index 93df4bf7a429a459ccd51603af035d96f3f9e3d6..7d67fc2d6f05207983969e2cd3a0c6aab9a3c0c2 100644
--- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h
+++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h
@@ -8,13 +8,11 @@
 // ArmarX
 #include <RobotAPI/interface/skills/SkillManagerInterface.h>
 #include <RobotAPI/interface/skills/SkillProviderInterface.h>
-
 #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h>
 
 namespace armarx::skills::segment
 {
-    class SkillEventCoreSegment :
-        public armem::server::segment::SpecializedCoreSegment
+    class SkillEventCoreSegment : public armem::server::segment::SpecializedCoreSegment
     {
         using Base = armem::server::segment::SpecializedCoreSegment;
 
@@ -23,11 +21,12 @@ namespace armarx::skills::segment
 
         SkillEventCoreSegment(armem::server::MemoryToIceAdapter& iceMemory);
 
-        void defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix);
+        void defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix);
         void init();
 
-        void addSkillUpdateEvent(const skills::provider::dto::SkillStatusUpdate& update);
+        void addSkillUpdateEvent(const skills::provider::dto::SkillStatusUpdate& update,
+                                 const std::string& providerName);
 
     private:
     };
-}
+} // namespace armarx::skills::segment
diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
index 2908d2e77a0a16627d65d2eb757d3ad8431c3271..5fbc2e925f5461514d4bec656762920935600ec3 100644
--- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
@@ -1,8 +1,12 @@
 #include "SkillManagerComponentPlugin.h"
 
 #include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/time/DateTime.h>
+#include <ArmarXCore/core/time/ice_conversions.h>
 
-#include "../error/Exception.h"
+#include <RobotAPI/libraries/skills/error/Exception.h>
+#include <RobotAPI/libraries/skills/provider/SkillID.h>
+#include <RobotAPI/libraries/skills/provider/SkillStatusUpdate.h>
 
 namespace armarx::plugins
 {
@@ -68,6 +72,7 @@ namespace armarx
     std::string
     SkillManagerComponentPluginUser::getFirstProviderNameThatHasSkill(const std::string& skillName)
     {
+        // NON LOCKING! WE ASSERT THAT THE CALLER HOLDS LOCK
         for (const auto& [providerName, providerPrx] : skillProviderMap)
         {
             auto allSkills = providerPrx->getSkillDescriptions();
@@ -85,12 +90,16 @@ namespace armarx
     using SkillProviderInterfacePrxMap =
         std::map<std::string, skills::provider::dti::SkillProviderInterfacePrx>;
 
-    skills::provider::dto::SkillStatusUpdate
+    skills::manager::dto::SkillStatusUpdate
     SkillManagerComponentPluginUser::executeSkill(
         const skills::manager::dto::SkillExecutionRequest& info,
         const Ice::Current&)
     {
+        std::unique_lock l(skillProviderMapMutex);
+
         std::string providerName = "INVALID PROVIDER NAME";
+
+        // TODO: Really support regexes!
         if (info.skillId.providerName == "*")
         {
             providerName = getFirstProviderNameThatHasSkill(info.skillId.skillName);
@@ -100,68 +109,61 @@ namespace armarx
             providerName = info.skillId.providerName;
         }
 
-        SkillProviderInterfacePrxMap skillProviderMap;
-        {
-            std::scoped_lock l(skillProviderMapMutex);
-            skillProviderMap = this->skillProviderMap;
-        }
 
-        bool remove = false;
         if (auto it = skillProviderMap.find(providerName); it != skillProviderMap.end())
         {
-            const auto& n = it->first;
-            const auto& s = it->second;
+            const auto& provider = it->second;
+
+            if (!provider)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
+                               << providerName << "'. Removing it from skills.";
+                skillProviderMap.erase(it);
+
+                throw skills::error::SkillException(
+                    __PRETTY_FUNCTION__,
+                    "Skill execution failed. Could not execute a skill of provider '" +
+                        providerName + "' because the provider does not exist.");
+            }
 
             try
             {
-                if (s)
-                {
-                    skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx;
-                    getProxy(myPrx, -1);
+                skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx;
+                getProxy(myPrx, -1);
 
-                    skills::provider::dto::SkillExecutionRequest exInfo;
-                    exInfo.skillName = info.skillId.skillName;
-                    exInfo.executorName = info.executorName;
-                    exInfo.callbackInterface = myPrx;
-                    exInfo.params = info.params;
+                skills::provider::dto::SkillExecutionRequest exInfo;
+                exInfo.skillName = info.skillId.skillName;
+                exInfo.executorName = info.executorName;
+                exInfo.callbackInterface = myPrx;
+                exInfo.params = info.params;
 
-                    return s->executeSkill(exInfo);
-                }
-                else
-                {
-                    remove = true;
-                }
+                auto async = provider->begin_executeSkill(exInfo);
+                l.unlock(); // allow parallel e.g. stopping
+                auto up = provider->end_executeSkill(async);
+
+                // convert to manager view
+                return skills::SkillStatusUpdate::FromIce(up, providerName).toIce();
             }
             catch (...)
             {
-                remove = true;
-            }
-
+                ARMARX_WARNING << __PRETTY_FUNCTION__
+                               << ": Found disconnected or buggy skill provider '" << providerName
+                               << "' during execution. Removing it from skills.";
+                skillProviderMap.erase(it);
 
-            if (remove)
-            {
-                std::scoped_lock l(skillProviderMapMutex);
-                // No copy!
-                SkillProviderInterfacePrxMap& skillProviderMap = this->skillProviderMap;
-                if (auto it = skillProviderMap.find(providerName); it != skillProviderMap.end())
-                {
-                    ARMARX_WARNING << __PRETTY_FUNCTION__
-                                   << ": Found disconnected or buggy skill provider '" << n
-                                   << "' during execution. Removing it from skills.";
-                    it = skillProviderMap.erase(it);
-                }
+                throw skills::error::SkillException(
+                    __PRETTY_FUNCTION__,
+                    "Skill execution failed. Could not execute a skill of provider '" +
+                        providerName + "' because the provider does not exist.");
             }
         }
         else
         {
-            ARMARX_ERROR << "Could not execute a skill of provider '" + providerName +
-                                "' because the provider does not exist.";
             throw skills::error::SkillException(
                 __PRETTY_FUNCTION__,
                 "Skill execution failed. Could not execute a skill of provider '" + providerName +
                     "' because the provider does not exist.");
         }
-        return {}; // Never happens
     }
 
     void
@@ -169,32 +171,30 @@ namespace armarx
                                                 const std::string& skillName,
                                                 const Ice::Current& current)
     {
-        SkillProviderInterfacePrxMap skillProviderMap;
-        {
-            std::scoped_lock l(skillProviderMapMutex);
-            skillProviderMap = this->skillProviderMap;
-        }
-
+        std::unique_lock l(skillProviderMapMutex);
         if (auto it = skillProviderMap.find(providerName); it != skillProviderMap.end())
         {
-            const auto& n = it->first;
-            const auto& s = it->second;
+            const auto& providerName = it->first;
+            const auto& provider = it->second;
+
+            if (!provider)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
+                               << providerName << "'. Removing it from skills.";
+                skillProviderMap.erase(it);
+                return;
+            }
+
             try
             {
-                if (s)
-                {
-                    s->abortSkill(skillName);
-                }
-                else
-                {
-                    ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
-                                   << n << "'. Removing it from skills on next execute.";
-                }
+                auto async = provider->begin_abortSkill(skillName);
+                l.unlock(); // allow parallel e.g. stopping
+                return provider->end_abortSkill(async);
             }
             catch (...)
             {
-                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" << n
-                               << "'. Removing it from skills on next execute.";
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '"
+                               << providerName << "'. Removing it from skills on next execute.";
             }
         }
     }
@@ -202,9 +202,11 @@ namespace armarx
     void
     SkillManagerComponentPluginUser::updateStatusForSkill(
         const skills::provider::dto::SkillStatusUpdate& statusUpdate,
+        const std::string& providerName,
         const Ice::Current&)
     {
         (void)statusUpdate;
+        (void)providerName;
         // If you want to use the status, implement this method!
     }
 
@@ -216,62 +218,127 @@ namespace armarx
         std::scoped_lock l(skillProviderMapMutex);
         for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();)
         {
-            const auto& n = it->first;
-            const auto& s = it->second;
+            const auto& providerName = it->first;
+            const auto& provider = it->second;
+
+            if (!provider)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
+                               << providerName << "'. Removing it from skills.";
+                it = skillProviderMap.erase(it);
+                continue;
+            }
+
             try
             {
-                if (s)
-                {
-                    skills::provider::dto::SkillDescriptionMap m = s->getSkillDescriptions();
-                    ret.insert({n, m});
-                    ++it;
-                }
-                else
-                {
-                    ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
-                                   << n << "'. Removing it from skills.";
-                    it = skillProviderMap.erase(it);
-                }
+                skills::provider::dto::SkillDescriptionMap m = provider->getSkillDescriptions();
+                ret.insert({providerName, m});
+                ++it;
             }
             catch (...)
             {
-                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" << n
-                               << "'. Removing it from skills.";
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '"
+                               << providerName << "'. Removing it from skills.";
                 it = skillProviderMap.erase(it);
             }
         }
         return ret;
     }
 
-    skills::manager::dto::SkillStatusUpdateMapMap
+    skills::manager::dto::SkillStatusUpdate
+    SkillManagerComponentPluginUser::getSkillExecutionStatus(
+        const skills::manager::dto::SkillExecutionID& executionId,
+        const Ice::Current& current)
+    {
+        skills::SkillExecutionId execId = skills::SkillExecutionId::FromIce(executionId);
+
+        std::unique_lock l(skillProviderMapMutex);
+        if (auto it = skillProviderMap.find(execId.skillId.providerName);
+            it != skillProviderMap.end())
+        {
+            const auto& providerName = it->first;
+            const auto& provider = it->second;
+
+            if (!provider)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
+                               << providerName << "'. Removing it from skills.";
+                skillProviderMap.erase(it);
+
+                throw skills::error::SkillException(__PRETTY_FUNCTION__,
+                                                    "Skill execution failed. Could not query a "
+                                                    "status update of a skill of provider '" +
+                                                        providerName +
+                                                        "' because the provider does not exist.");
+            }
+
+            try
+            {
+                auto async = provider->begin_getSkillExecutionStatus(execId.toIceProviderView());
+                l.unlock(); // allow parallel e.g. stopping
+                auto up = provider->end_getSkillExecutionStatus(async);
+
+                // convert to manager view
+                return skills::SkillStatusUpdate::FromIce(up, providerName).toIce();
+            }
+            catch (...)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__
+                               << ": Found disconnected or buggy skill provider '" << providerName
+                               << "' during execution. Removing it from skills.";
+                skillProviderMap.erase(it);
+
+                throw skills::error::SkillException(__PRETTY_FUNCTION__,
+                                                    "Skill execution failed. Could not query a "
+                                                    "status update of a skill of provider '" +
+                                                        providerName +
+                                                        "' because the provider does not exist.");
+            }
+        }
+        else
+        {
+            // no actove skill. Return idle
+            skills::SkillStatusUpdate idle;
+            idle.executionId = execId;
+            return idle.toIce();
+        }
+    }
+
+    skills::manager::dto::SkillStatusUpdateList
     SkillManagerComponentPluginUser::getSkillExecutionStatuses(const Ice::Current& current)
     {
-        skills::manager::dto::SkillStatusUpdateMapMap ret;
+        skills::manager::dto::SkillStatusUpdateList ret;
 
         std::scoped_lock l(skillProviderMapMutex);
         for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();)
         {
-            const auto& n = it->first;
-            const auto& s = it->second;
+            const auto& providerName = it->first;
+            const auto& provider = it->second;
+
+            if (!provider)
+            {
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
+                               << providerName << "'. Removing it from skills.";
+                it = skillProviderMap.erase(it);
+                continue;
+            }
+
             try
             {
-                if (s)
-                {
-                    skills::provider::dto::SkillStatusUpdateMap m = s->getSkillExecutionStatuses();
-                    ret.insert({n, m});
-                    it++;
-                }
-                else
+                skills::provider::dto::SkillStatusUpdateList m =
+                    provider->getSkillExecutionStatuses();
+
+                for (const auto& up : m)
                 {
-                    ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '"
-                                   << n << "'. Removing it from skills.";
-                    it = skillProviderMap.erase(it);
+                    // convert provider view to manager view
+                    ret.push_back(skills::SkillStatusUpdate::FromIce(up, providerName).toIce());
                 }
+                it++;
             }
             catch (...)
             {
-                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" << n
-                               << "'. Removing it from skills.";
+                ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '"
+                               << providerName << "'. Removing it from skills.";
                 it = skillProviderMap.erase(it);
             }
         }
diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h
index 7b14adf04d141900166968c773f498b6060623cb..cd3a576dec2cb53ee419f29de5db6546ac66ea09 100644
--- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h
+++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h
@@ -20,26 +20,40 @@ namespace armarx::plugins
 
         void postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) override;
     };
-}
+} // namespace armarx::plugins
 
 namespace armarx
 {
     class SkillManagerComponentPluginUser :
-            virtual public ManagedIceObject,
-            virtual public skills::manager::dti::SkillManagerInterface
+        virtual public ManagedIceObject,
+        virtual public skills::manager::dti::SkillManagerInterface
     {
     public:
         SkillManagerComponentPluginUser();
 
-        void addProvider(const skills::manager::dto::ProviderInfo& providerInfo, const Ice::Current &current) override;
-        void removeProvider(const std::string&, const Ice::Current &current) override;
+        void addProvider(const skills::manager::dto::ProviderInfo& providerInfo,
+                         const Ice::Current& current) override;
+        void removeProvider(const std::string&, const Ice::Current& current) override;
 
-        skills::provider::dto::SkillStatusUpdate executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current &current) override;
-        void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, const Ice::Current &current) override;
-        void abortSkill(const std::string& providerName, const std::string& skillName, const Ice::Current &current) override;
+        skills::manager::dto::SkillStatusUpdate
+        executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
+                     const Ice::Current& current) override;
+        void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
+                                  const std::string& providerName,
+                                  const Ice::Current& current) override;
+        void abortSkill(const std::string& providerName,
+                        const std::string& skillName,
+                        const Ice::Current& current) override;
 
-        skills::manager::dto::SkillDescriptionMapMap getSkillDescriptions(const Ice::Current &current) override;
-        skills::manager::dto::SkillStatusUpdateMapMap getSkillExecutionStatuses(const Ice::Current &current) override;
+        skills::manager::dto::SkillDescriptionMapMap
+        getSkillDescriptions(const Ice::Current& current) override;
+
+        skills::manager::dto::SkillStatusUpdate
+        getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId,
+                                const Ice::Current& current) override;
+
+        skills::manager::dto::SkillStatusUpdateList
+        getSkillExecutionStatuses(const Ice::Current& current) override;
 
     protected:
         std::string getFirstProviderNameThatHasSkill(const std::string& skillName);
@@ -51,4 +65,4 @@ namespace armarx
         std::mutex skillProviderMapMutex;
         std::map<std::string, skills::provider::dti::SkillProviderInterfacePrx> skillProviderMap;
     };
-}
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillID.cpp b/source/RobotAPI/libraries/skills/provider/SkillID.cpp
index 07c6248b2f8c366ceeb7782b78315a6d16f74c70..a384261f876673b680d8bd102a1439ef05744fcb 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillID.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillID.cpp
@@ -4,42 +4,63 @@ namespace armarx
 {
     namespace skills
     {
-        SkillID::SkillID(const std::string& providerName, const std::string& skillName) : providerName(providerName), skillName(skillName)
+        SkillID::SkillID(const std::string& providerName, const std::string& skillName) :
+            providerName(providerName), skillName(skillName)
         {
-            if (simox::alg::contains(providerName, NAME_SEPARATOR) || simox::alg::contains(skillName, NAME_SEPARATOR))
+            if (simox::alg::contains(providerName, NAME_SEPARATOR) ||
+                simox::alg::contains(skillName, NAME_SEPARATOR))
             {
-                throw error::SkillException(__PRETTY_FUNCTION__, std::string("A skill provider or a skill contains the blacklisted token '") + NAME_SEPARATOR + "'.");
+                throw error::SkillException(
+                    __PRETTY_FUNCTION__,
+                    std::string("A skill provider or a skill contains the blacklisted token '") +
+                        NAME_SEPARATOR + "'.");
             }
 
-            if (simox::alg::contains(providerName, PREFIX_SEPARATOR) || simox::alg::contains(skillName, PREFIX_SEPARATOR))
+            if (simox::alg::contains(providerName, PREFIX_SEPARATOR) ||
+                simox::alg::contains(skillName, PREFIX_SEPARATOR))
             {
-                throw error::SkillException(__PRETTY_FUNCTION__, std::string("A skill provider or a skill contains the blacklisted token '") + PREFIX_SEPARATOR + "'.");
+                throw error::SkillException(
+                    __PRETTY_FUNCTION__,
+                    std::string("A skill provider or a skill contains the blacklisted token '") +
+                        PREFIX_SEPARATOR + "'.");
             }
         }
 
-        bool SkillID::operator==(const SkillID& other) const
+        bool
+        SkillID::operator==(const SkillID& other) const
         {
-            return toString() == other.toString();
+            return providerName == other.providerName && skillName == other.skillName;
         }
 
-        bool SkillID::operator<(const SkillID& other) const
+        bool
+        SkillID::operator!=(const SkillID& other) const
+        {
+            return not(*this == other);
+        }
+
+        bool
+        SkillID::operator<(const SkillID& other) const
         {
             return toString() < other.toString();
         }
 
-        provider::dto::SkillID SkillID::toIce() const
+        manager::dto::SkillID
+        SkillID::toIce() const
         {
             return {providerName, skillName};
         }
 
-        std::string SkillID::toString(const std::string& prefix) const
+        std::string
+        SkillID::toString(const std::string& prefix) const
         {
-            return (prefix.empty() ? std::string("") : (prefix + PREFIX_SEPARATOR)) + providerName + NAME_SEPARATOR + skillName;
+            return (prefix.empty() ? std::string("") : (prefix + PREFIX_SEPARATOR)) + providerName +
+                   NAME_SEPARATOR + skillName;
         }
-    }
+    } // namespace skills
 
-    std::ostream& skills::operator<<(std::ostream& os, const SkillID& id)
+    std::ostream&
+    skills::operator<<(std::ostream& os, const SkillID& id)
     {
         return os << "'" << id.toString() << "'";
     }
-}
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillID.h b/source/RobotAPI/libraries/skills/provider/SkillID.h
index 320a6e946e04694c6d703d0f78b18552d756cf7d..3eb1fd6f4dac0d7fdb9e2d7b258a968f548e8a14 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillID.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillID.h
@@ -5,10 +5,10 @@
 
 #include <SimoxUtility/algorithm/string.h>
 
-#include "../error/Exception.h"
-
+#include <RobotAPI/interface/skills/SkillManagerInterface.h>
 #include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
-#include <RobotAPI/interface/skills/SkillProviderInterface.h>
+
+#include "../error/Exception.h"
 
 namespace armarx
 {
@@ -27,12 +27,13 @@ namespace armarx
             SkillID(const std::string& providerName, const std::string& skillName);
 
             bool operator==(const SkillID& other) const;
+            bool operator!=(const SkillID& other) const;
             bool operator<(const SkillID& other) const;
 
-            provider::dto::SkillID toIce() const;
+            manager::dto::SkillID toIce() const;
             std::string toString(const std::string& prefix = "") const;
         };
 
         std::ostream& operator<<(std::ostream& os, const SkillID& id);
-    }
-}
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillParameterization.cpp b/source/RobotAPI/libraries/skills/provider/SkillParameterization.cpp
index f977b2ac595fd3506856d2ba42468cdef72d2e54..d0ec681e2b772aa773a6cc890198e24c28714207 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillParameterization.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillParameterization.cpp
@@ -4,9 +4,5 @@ namespace armarx
 {
     namespace skills
     {
-        aron::data::dto::DictPtr SkillParameterization::toIce() const
-        {
-            return aron::data::Dict::ToAronDictDTO(usedInputParams);
-        }
     }
-}
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillParameterization.h b/source/RobotAPI/libraries/skills/provider/SkillParameterization.h
index 72ec6d2eb11eec1954e753021d6e634a641027fd..65261a5cb939f72b69ea46c1807e52640752c9cb 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillParameterization.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillParameterization.h
@@ -12,10 +12,8 @@ namespace armarx
     {
         struct SkillParameterization
         {
-            aron::data::DictPtr                                 usedInputParams = nullptr;
-            callback::dti::SkillProviderCallbackInterfacePrx    usedCallbackInterface = nullptr;
-
-            aron::data::dto::DictPtr toIce() const;
+            aron::data::DictPtr usedInputParams = nullptr;
+            callback::dti::SkillProviderCallbackInterfacePrx usedCallbackInterface = nullptr;
         };
-    }
-}
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
index c76da14105facaf03ff55742b22ac968fe1fd196..e4ca565aa54b7e1f48f0d1d16b1c87c096e29599 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
@@ -29,8 +29,6 @@ namespace armarx::plugins
         {
             impl.skill->manager = manager;
             impl.skill->providerName = providerName;
-
-            impl.statusUpdate.skillId = {providerName, skillName};
         }
 
         // register self to manager
@@ -80,17 +78,9 @@ namespace armarx::plugins
         }
 
         std::string skillName = skill->description.skillName;
-        if (connected) // TODO: fix so that skills can be added anytime!!!
-        {
-            ARMARX_WARNING << "The SkillProvider already registered to a manager. The skill '" +
-                                  skillName +
-                                  "' therefore cannot be added anymore. Please only add skills in "
-                                  "the onInit method.";
-            return;
-        }
 
         // lock skills map
-        const std::unique_lock l(skillsMutex);
+        const std::unique_lock l(skillImplementationsMapMutex);
         if (skillImplementations.find(skillName) != skillImplementations.end())
         {
             ARMARX_WARNING << "Try to add a skill '" + skillName +
@@ -100,7 +90,14 @@ namespace armarx::plugins
 
         ARMARX_INFO << "Adding skill and set owning provider name" << skillName;
         auto s = skillImplementations.emplace(skillName, std::move(skill));
-        s.first->second.statusUpdate.skillId = skills::SkillID(parent().getName(), skillName);
+
+        if (connected)
+        {
+            // if skill is added after onConnect we have to set the proxies manually.
+            std::string providerName = parent().getName();
+            s.first->second.skill->manager = manager;
+            s.first->second.skill->providerName = providerName;
+        }
     }
 
     skills::detail::SkillImplementationWrapper&
@@ -108,19 +105,23 @@ namespace armarx::plugins
     {
         ARMARX_CHECK_GREATER(skillImplementations.count(name), 0)
             << "Skill '" + name + "' not found.";
-        const std::unique_lock l(skillsMutex);
+        const std::unique_lock l(skillImplementationsMapMutex);
         return skillImplementations.at(name);
     }
 
-    skills::provider::dto::SkillStatusUpdateMap
+    skills::provider::dto::SkillStatusUpdateList
     SkillProviderComponentPlugin::getSkillExecutionStatuses() const
     {
-        skills::provider::dto::SkillStatusUpdateMap skillUpdates;
-        const std::unique_lock l(skillsMutex);
+        skills::provider::dto::SkillStatusUpdateList skillUpdates;
+        const std::unique_lock l(skillImplementationsMapMutex);
         for (const auto& [key, impl] : skillImplementations)
         {
-            const std::shared_lock l2(impl.skillStatusMutex);
-            skillUpdates.insert({key, impl.statusUpdate.toIce()});
+            const std::shared_lock l2(impl.skillStatusesMutex);
+            for (const auto& [execId, up] : impl.statusUpdates)
+            {
+                (void)execId;
+                skillUpdates.push_back(up.toIceProviderView());
+            }
         }
         return skillUpdates;
     }
@@ -129,7 +130,7 @@ namespace armarx::plugins
     SkillProviderComponentPlugin::getSkillDescriptions() const
     {
         skills::provider::dto::SkillDescriptionMap skillDesciptions;
-        const std::unique_lock l(skillsMutex);
+        const std::unique_lock l(skillImplementationsMapMutex);
         for (const auto& [key, impl] : skillImplementations)
         {
             skillDesciptions.insert({key, impl.skill->description.toIce()});
@@ -175,16 +176,29 @@ namespace armarx
     }
 
     skills::provider::dto::SkillStatusUpdate
-    SkillProviderComponentPluginUser::getSkillExecutionStatus(const std::string& skill,
-                                                              const Ice::Current& /*unused*/)
+    SkillProviderComponentPluginUser::getSkillExecutionStatus(
+        const skills::provider::dto::SkillExecutionID& executionId,
+        const Ice::Current& /*unused*/)
     {
-        auto& skillWrapper = plugin->getSkill(skill);
+        auto execId = skills::SkillExecutionId::FromIce(executionId, getName());
+
+        auto& skillWrapper = plugin->getSkill(executionId.skillName);
 
-        const std::shared_lock l(skillWrapper.skillStatusMutex);
-        return skillWrapper.statusUpdate.toIce();
+        const std::shared_lock l(skillWrapper.skillStatusesMutex);
+        if (auto it = skillWrapper.statusUpdates.find(execId);
+            it != skillWrapper.statusUpdates.end())
+        {
+            return it->second.toIceProviderView();
+        }
+        else
+        {
+            skills::SkillStatusUpdate idle;
+            idle.executionId = execId;
+            return idle.toIceProviderView();
+        }
     }
 
-    skills::provider::dto::SkillStatusUpdateMap
+    skills::provider::dto::SkillStatusUpdateList
     SkillProviderComponentPluginUser::getSkillExecutionStatuses(const Ice::Current& /*unused*/)
     {
         return plugin->getSkillExecutionStatuses();
@@ -196,7 +210,7 @@ namespace armarx
         const skills::provider::dto::SkillExecutionRequest& info,
         const Ice::Current& /*unused*/)
     {
-        // The skill will be executed in a different thread
+        // The skill will be executed in a seperate thread
         std::thread execution;
 
         // setup input args for skill execution
@@ -215,7 +229,7 @@ namespace armarx
                 {
                     // execute waits until the previous execution finishes.
                     auto x = wrapper.setupAndExecuteSkill(info.executorName, usedParameterization);
-                    ret = x.toIce();
+                    ret = x.toIceProviderView();
                 });
         } // release lock. We don't know how long the skill needs to finish and we have to release the lock for being able to abort the execution
 
@@ -227,7 +241,8 @@ namespace armarx
     }
 
     void
-    SkillProviderComponentPluginUser::abortSkill(const std::string& skillName, const Ice::Current& /*unused*/)
+    SkillProviderComponentPluginUser::abortSkill(const std::string& skillName,
+                                                 const Ice::Current& /*unused*/)
     {
         auto& wrapper = plugin->getSkill(skillName);
         wrapper.skill->notifySkillToStopASAP();
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
index 6b74dd1e2479068ca920dde2b8f2ec102b0d7646..d6bfe6e059f799a89a2a611220812c798b1f4cd6 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
@@ -1,11 +1,11 @@
 #pragma once
 
+#include <experimental/memory>
 #include <functional>
 #include <queue>
 #include <shared_mutex>
 #include <thread>
 #include <type_traits>
-#include <experimental/memory>
 
 #include <ArmarXCore/core/ComponentPlugin.h>
 #include <ArmarXCore/core/ManagedIceObject.h>
@@ -23,10 +23,12 @@
 
 // Helper wrapper for execution
 #include "detail/SkillImplementationWrapper.h"
+
 namespace armarx
 {
     class SkillProviderComponentPluginUser; // forward declaration
 }
+
 namespace armarx::plugins
 {
     class SkillProviderComponentPlugin : public ComponentPlugin
@@ -61,15 +63,16 @@ namespace armarx::plugins
             return static_cast<T*>(skillPtr);
         }
 
+        skills::provider::dto::SkillStatusUpdateList getSkillExecutionStatuses() const;
+        skills::provider::dto::SkillDescriptionMap getSkillDescriptions() const;
+
     private:
         skills::detail::SkillImplementationWrapper& getSkill(const std::string& name);
-        skills::provider::dto::SkillStatusUpdateMap getSkillExecutionStatuses() const;
-        skills::provider::dto::SkillDescriptionMap getSkillDescriptions() const;
 
         skills::manager::dti::SkillManagerInterfacePrx manager;
         skills::provider::dti::SkillProviderInterfacePrx myPrx;
 
-        mutable std::shared_mutex skillsMutex;
+        mutable std::mutex skillImplementationsMapMutex;
 
         bool connected = false;
         std::map<std::string, skills::detail::SkillImplementationWrapper> skillImplementations;
@@ -93,9 +96,9 @@ namespace armarx
         skills::provider::dto::SkillDescriptionMap
         getSkillDescriptions(const Ice::Current& current = Ice::Current()) override;
         skills::provider::dto::SkillStatusUpdate
-        getSkillExecutionStatus(const std::string& skill,
+        getSkillExecutionStatus(const skills::provider::dto::SkillExecutionID& executionId,
                                 const Ice::Current& current = Ice::Current()) override;
-        skills::provider::dto::SkillStatusUpdateMap
+        skills::provider::dto::SkillStatusUpdateList
         getSkillExecutionStatuses(const Ice::Current& current = Ice::Current()) override;
 
         skills::provider::dto::SkillStatusUpdate
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProxy.h b/source/RobotAPI/libraries/skills/provider/SkillProxy.h
index 32058b174ccdbde31ed50edcc626ad13b5aa3873..c9ea3f09f8eb8f9e57b23a09226d8d1903ab2644 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProxy.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillProxy.h
@@ -41,9 +41,6 @@ namespace armarx
                                                     const std::string& profileName,
                                                     const aron::data::DictPtr& params = nullptr);
 
-
-            void abortSkill(const std::string& executorName);
-
         private:
             const manager::dti::SkillManagerInterfacePrx& manager;
 
diff --git a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp
index 18c4b8647bf3390a64343546b278155ab6a9ce30..8a7ac2ab532bb0d0817e1894ae2565014f1940fa 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp
@@ -4,7 +4,8 @@ namespace armarx
 {
     namespace skills
     {
-        SkillStatus toSkillStatus(const ActiveOrTerminatedSkillStatus& d)
+        SkillStatus
+        toSkillStatus(const ActiveOrTerminatedSkillStatus& d)
         {
             switch (d)
             {
@@ -20,7 +21,8 @@ namespace armarx
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
-        SkillStatus toSkillStatus(const TerminatedSkillStatus& d)
+        SkillStatus
+        toSkillStatus(const TerminatedSkillStatus& d)
         {
             switch (d)
             {
@@ -34,72 +36,76 @@ namespace armarx
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
-        void toIce(provider::dto::Execution::Status& ret, const SkillStatus& status)
+        void
+        toIce(provider::dto::Execution::Status& ret, const SkillStatus& status)
         {
-            switch(status)
+            switch (status)
             {
                 case SkillStatus::Idle:
-                    ret =  provider::dto::Execution::Status::Idle;
+                    ret = provider::dto::Execution::Status::Idle;
                     return;
                 case SkillStatus::Scheduled:
-                    ret =  provider::dto::Execution::Status::Scheduled;
+                    ret = provider::dto::Execution::Status::Scheduled;
                     return;
                 case SkillStatus::Running:
-                    ret =  provider::dto::Execution::Status::Running;
+                    ret = provider::dto::Execution::Status::Running;
                     return;
                 case SkillStatus::Failed:
-                    ret =  provider::dto::Execution::Status::Failed;
+                    ret = provider::dto::Execution::Status::Failed;
                     return;
                 case SkillStatus::Succeeded:
-                    ret =  provider::dto::Execution::Status::Succeeded;
+                    ret = provider::dto::Execution::Status::Succeeded;
                     return;
                 case SkillStatus::Aborted:
-                    ret =  provider::dto::Execution::Status::Aborted;
+                    ret = provider::dto::Execution::Status::Aborted;
                     return;
             }
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
-        void toIce(provider::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status)
+        void
+        toIce(provider::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status)
         {
-            switch(status)
+            switch (status)
             {
                 case ActiveOrTerminatedSkillStatus::Running:
-                    ret =  provider::dto::Execution::Status::Running;
+                    ret = provider::dto::Execution::Status::Running;
                     return;
                 case ActiveOrTerminatedSkillStatus::Failed:
-                    ret =  provider::dto::Execution::Status::Failed;
+                    ret = provider::dto::Execution::Status::Failed;
                     return;
                 case ActiveOrTerminatedSkillStatus::Succeeded:
-                    ret =  provider::dto::Execution::Status::Succeeded;
+                    ret = provider::dto::Execution::Status::Succeeded;
                     return;
                 case ActiveOrTerminatedSkillStatus::Aborted:
-                    ret =  provider::dto::Execution::Status::Aborted;
+                    ret = provider::dto::Execution::Status::Aborted;
                     return;
             }
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
-        void toIce(provider::dto::Execution::Status& ret, const TerminatedSkillStatus& status)
+        void
+        toIce(provider::dto::Execution::Status& ret, const TerminatedSkillStatus& status)
         {
-            switch(status)
+            switch (status)
             {
                 case TerminatedSkillStatus::Failed:
-                    ret =  provider::dto::Execution::Status::Failed;
+                    ret = provider::dto::Execution::Status::Failed;
                     return;
                 case TerminatedSkillStatus::Succeeded:
-                    ret =  provider::dto::Execution::Status::Succeeded;
+                    ret = provider::dto::Execution::Status::Succeeded;
                     return;
                 case TerminatedSkillStatus::Aborted:
-                    ret =  provider::dto::Execution::Status::Aborted;
+                    ret = provider::dto::Execution::Status::Aborted;
                     return;
             }
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
-        void fromIce(const provider::dto::Execution::Status& status, TerminatedSkillStatus& ret)
+        void
+        fromIce(const provider::dto::Execution::Status& status, TerminatedSkillStatus& ret)
         {
-            switch(status)
+            switch (status)
             {
                 case provider::dto::Execution::Status::Idle:
                     [[fallthrough]];
@@ -108,138 +114,331 @@ namespace armarx
                 case provider::dto::Execution::Status::Running:
                     break;
                 case provider::dto::Execution::Status::Failed:
-                    ret =  TerminatedSkillStatus::Failed;
+                    ret = TerminatedSkillStatus::Failed;
                     return;
                 case provider::dto::Execution::Status::Succeeded:
-                    ret =  TerminatedSkillStatus::Succeeded;
+                    ret = TerminatedSkillStatus::Succeeded;
                     return;
                 case provider::dto::Execution::Status::Aborted:
-                    ret =  TerminatedSkillStatus::Aborted;
+                    ret = TerminatedSkillStatus::Aborted;
                     return;
             }
-            throw error::SkillException(__PRETTY_FUNCTION__, "You entered an invalid execution status type to convert to a terminating status.");
+            throw error::SkillException(
+                __PRETTY_FUNCTION__,
+                "You entered an invalid execution status type to convert to a terminating status.");
         }
 
-        void fromIce(const provider::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret)
+        void
+        fromIce(const provider::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret)
         {
-            switch(status)
+            switch (status)
             {
                 case provider::dto::Execution::Status::Idle:
                     [[fallthrough]];
                 case provider::dto::Execution::Status::Scheduled:
                     break;
                 case provider::dto::Execution::Status::Running:
-                    ret =  ActiveOrTerminatedSkillStatus::Running;
+                    ret = ActiveOrTerminatedSkillStatus::Running;
                     return;
                 case provider::dto::Execution::Status::Failed:
-                    ret =  ActiveOrTerminatedSkillStatus::Failed;
+                    ret = ActiveOrTerminatedSkillStatus::Failed;
                     return;
                 case provider::dto::Execution::Status::Succeeded:
-                    ret =  ActiveOrTerminatedSkillStatus::Succeeded;
+                    ret = ActiveOrTerminatedSkillStatus::Succeeded;
                     return;
                 case provider::dto::Execution::Status::Aborted:
-                    ret =  ActiveOrTerminatedSkillStatus::Aborted;
+                    ret = ActiveOrTerminatedSkillStatus::Aborted;
                     return;
             }
-            throw error::SkillException(__PRETTY_FUNCTION__, "You entered an invalid execution status type to convert to a terminating status.");
+            throw error::SkillException(
+                __PRETTY_FUNCTION__,
+                "You entered an invalid execution status type to convert to a terminating status.");
         }
 
-        void fromIce(const provider::dto::Execution::Status& status, SkillStatus& ret)
+        void
+        fromIce(const provider::dto::Execution::Status& status, SkillStatus& ret)
         {
-            switch(status)
+            switch (status)
             {
                 case provider::dto::Execution::Status::Idle:
-                    ret =  SkillStatus::Idle;
+                    ret = SkillStatus::Idle;
                     return;
                 case provider::dto::Execution::Status::Scheduled:
-                    ret =  SkillStatus::Scheduled;
+                    ret = SkillStatus::Scheduled;
                     return;
                 case provider::dto::Execution::Status::Running:
-                    ret =  SkillStatus::Running;
+                    ret = SkillStatus::Running;
                     return;
                 case provider::dto::Execution::Status::Failed:
-                    ret =  SkillStatus::Failed;
+                    ret = SkillStatus::Failed;
                     return;
                 case provider::dto::Execution::Status::Succeeded:
-                    ret =  SkillStatus::Succeeded;
+                    ret = SkillStatus::Succeeded;
                     return;
                 case provider::dto::Execution::Status::Aborted:
-                    ret =  SkillStatus::Aborted;
+                    ret = SkillStatus::Aborted;
                     return;
             }
             throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
         }
 
+        skills::manager::dto::SkillExecutionID
+        SkillExecutionId::toIce() const
+        {
+            skills::manager::dto::SkillExecutionID ret;
+            ret.skillId.skillName = skillId.skillName;
+            ret.skillId.providerName = skillId.providerName;
+            ret.executorName = executorName;
+            armarx::core::time::toIce(ret.executionStartedTime, executionStartedTime);
+            return ret;
+        }
 
+        skills::provider::dto::SkillExecutionID
+        SkillExecutionId::toIceProviderView() const
+        {
+            skills::provider::dto::SkillExecutionID ret;
+            ret.skillName = skillId.skillName;
+            ret.executorName = executorName;
+            armarx::core::time::toIce(ret.executionStartedTime, executionStartedTime);
+            return ret;
+        }
 
+        void
+        SkillExecutionId::fromIce(const skills::manager::dto::SkillExecutionID& i)
+        {
+            skillId.skillName = i.skillId.skillName;
+            skillId.providerName = i.skillId.providerName;
+            executorName = i.executorName;
+            armarx::core::time::fromIce(i.executionStartedTime, executionStartedTime);
+        }
 
-        provider::dto::SkillStatusUpdate TerminatedSkillStatusUpdate::toIce() const
+        void
+        SkillExecutionId::fromIce(const skills::provider::dto::SkillExecutionID& i,
+                                  const std::string& providerName)
         {
-            provider::dto::SkillStatusUpdate ret;
-            ret.header.skillId = skillId.toIce();
-            ret.header.executorName = executorName;
-            ret.data = aron::data::Dict::ToAronDictDTO(data);
-            skills::toIce(ret.header.status, status);
+            skillId.skillName = i.skillName;
+            skillId.providerName = providerName;
+            executorName = i.executorName;
+            armarx::core::time::fromIce(i.executionStartedTime, executionStartedTime);
+        }
+
+        SkillExecutionId
+        SkillExecutionId::FromIce(const skills::manager::dto::SkillExecutionID& i)
+        {
+            SkillExecutionId ret;
+            ret.fromIce(i);
+            return ret;
+        }
+
+        SkillExecutionId
+        SkillExecutionId::FromIce(const skills::provider::dto::SkillExecutionID& i,
+                                  const std::string& providerName)
+        {
+            SkillExecutionId ret;
+            ret.fromIce(i, providerName);
+            return ret;
+        }
+
+        manager::dto::SkillStatusUpdate
+        SkillStatusUpdateBase::toIce() const
+        {
+            manager::dto::SkillStatusUpdate ret;
+            ret.header.executionId.skillId = executionId.skillId.toIce();
+            ret.header.executionId.executorName = executionId.executorName;
+            armarx::core::time::toIce(ret.header.executionId.executionStartedTime,
+                                      executionId.executionStartedTime);
+            ret.header.usedParams =
+                aron::data::Dict::ToAronDictDTO(usedParameterization.usedInputParams);
             ret.header.usedCallbackInterface = usedParameterization.usedCallbackInterface;
-            ret.header.usedParams = usedParameterization.toIce();
+            ret.data = aron::data::Dict::ToAronDictDTO(data);
             return ret;
         }
 
-        provider::dto::SkillStatusUpdate SkillStatusUpdate::toIce() const
+        provider::dto::SkillStatusUpdate
+        SkillStatusUpdateBase::toIceProviderView() const
         {
             provider::dto::SkillStatusUpdate ret;
-            ret.header.skillId = skillId.toIce();
-            ret.header.executorName = executorName;
+            ret.header.executionId.skillName = executionId.skillId.skillName;
+            ret.header.executionId.executorName = executionId.executorName;
+            armarx::core::time::toIce(ret.header.executionId.executionStartedTime,
+                                      executionId.executionStartedTime);
+            ret.header.usedParams =
+                aron::data::Dict::ToAronDictDTO(usedParameterization.usedInputParams);
+            ret.header.usedCallbackInterface = usedParameterization.usedCallbackInterface;
             ret.data = aron::data::Dict::ToAronDictDTO(data);
+            return ret;
+        }
+
+        void
+        SkillStatusUpdateBase::fromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            executionId.skillId = {update.header.executionId.skillId.providerName,
+                                   update.header.executionId.skillId.skillName};
+            executionId.executorName = update.header.executionId.executorName;
+            armarx::core::time::fromIce(update.header.executionId.executionStartedTime,
+                                        executionId.executionStartedTime);
+            usedParameterization.usedInputParams =
+                armarx::aron::data::Dict::FromAronDictDTO(update.header.usedParams);
+            usedParameterization.usedCallbackInterface = update.header.usedCallbackInterface;
+            data = armarx::aron::data::Dict::FromAronDictDTO(update.data);
+        }
+
+        void
+        SkillStatusUpdateBase::fromIce(const provider::dto::SkillStatusUpdate& update,
+                                       const std::string& providerName)
+        {
+            executionId.skillId = {providerName, update.header.executionId.skillName};
+            executionId.executorName = update.header.executionId.executorName;
+            armarx::core::time::fromIce(update.header.executionId.executionStartedTime,
+                                        executionId.executionStartedTime);
+            usedParameterization.usedInputParams =
+                armarx::aron::data::Dict::FromAronDictDTO(update.header.usedParams);
+            usedParameterization.usedCallbackInterface = update.header.usedCallbackInterface;
+            data = armarx::aron::data::Dict::FromAronDictDTO(update.data);
+        }
+
+        manager::dto::SkillStatusUpdate
+        TerminatedSkillStatusUpdate::toIce() const
+        {
+            manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIce();
             skills::toIce(ret.header.status, status);
-            ret.header.usedCallbackInterface = usedParameterization.usedCallbackInterface;
-            ret.header.usedParams = usedParameterization.toIce();
             return ret;
         }
 
-        provider::dto::SkillStatusUpdate ActiveOrTerminatedSkillStatusUpdate::toIce() const
+        provider::dto::SkillStatusUpdate
+        TerminatedSkillStatusUpdate::toIceProviderView() const
         {
-            provider::dto::SkillStatusUpdate ret;
-            ret.header.skillId = skillId.toIce();
-            ret.header.executorName = executorName;
-            ret.data = aron::data::Dict::ToAronDictDTO(data);
+            provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIceProviderView();
             skills::toIce(ret.header.status, status);
-            ret.header.usedCallbackInterface = usedParameterization.usedCallbackInterface;
-            ret.header.usedParams = usedParameterization.toIce();
             return ret;
         }
 
-        TerminatedSkillStatusUpdate TerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update)
+        manager::dto::SkillStatusUpdate
+        SkillStatusUpdate::toIce() const
+        {
+            manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIce();
+            skills::toIce(ret.header.status, status);
+            return ret;
+        }
+
+        provider::dto::SkillStatusUpdate
+        SkillStatusUpdate::toIceProviderView() const
+        {
+            provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIceProviderView();
+            skills::toIce(ret.header.status, status);
+            return ret;
+        }
+
+        manager::dto::SkillStatusUpdate
+        ActiveOrTerminatedSkillStatusUpdate::toIce() const
+        {
+            manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIce();
+            skills::toIce(ret.header.status, status);
+            return ret;
+        }
+
+        provider::dto::SkillStatusUpdate
+        ActiveOrTerminatedSkillStatusUpdate::toIceProviderView() const
+        {
+            provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toIceProviderView();
+            skills::toIce(ret.header.status, status);
+            return ret;
+        }
+
+        void
+        TerminatedSkillStatusUpdate::fromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            SkillStatusUpdateBase::fromIce(update);
+            skills::fromIce(update.header.status, status);
+        }
+
+        void
+        TerminatedSkillStatusUpdate::fromIce(const provider::dto::SkillStatusUpdate& update,
+                                             const std::string& providerName)
+        {
+            SkillStatusUpdateBase::fromIce(update, providerName);
+            skills::fromIce(update.header.status, status);
+        }
+
+        TerminatedSkillStatusUpdate
+        TerminatedSkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            TerminatedSkillStatusUpdate ret;
+            ret.fromIce(update);
+            return ret;
+        }
+
+        TerminatedSkillStatusUpdate
+        TerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update,
+                                             const std::string& providerName)
         {
             TerminatedSkillStatusUpdate ret;
-            ret.skillId = {update.header.skillId.providerName, update.header.skillId.skillName};
-            ret.executorName = update.header.executorName;
-            skills::fromIce(update.header.status, ret.status);
-            ret.usedParameterization = {aron::data::Dict::FromAronDictDTO(update.header.usedParams), update.header.usedCallbackInterface};
-            ret.data = aron::data::Dict::FromAronDictDTO(update.data);
+            ret.fromIce(update, providerName);
             return ret;
         }
 
-        SkillStatusUpdate SkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update)
+        void
+        SkillStatusUpdate::fromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            SkillStatusUpdateBase::fromIce(update);
+            skills::fromIce(update.header.status, status);
+        }
+
+        void
+        SkillStatusUpdate::fromIce(const provider::dto::SkillStatusUpdate& update,
+                                   const std::string& providerName)
+        {
+            SkillStatusUpdateBase::fromIce(update, providerName);
+            skills::fromIce(update.header.status, status);
+        }
+
+        SkillStatusUpdate
+        SkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            SkillStatusUpdate ret;
+            ret.fromIce(update);
+            return ret;
+        }
+
+        SkillStatusUpdate
+        SkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update,
+                                   const std::string& providerName)
         {
             SkillStatusUpdate ret;
-            ret.skillId = {update.header.skillId.providerName, update.header.skillId.skillName};
-            ret.executorName = update.header.executorName;
-            skills::fromIce(update.header.status, ret.status);
-            ret.usedParameterization = {aron::data::Dict::FromAronDictDTO(update.header.usedParams), update.header.usedCallbackInterface};
-            ret.data = aron::data::Dict::FromAronDictDTO(update.data);
+            ret.fromIce(update, providerName);
+            return ret;
+        }
+
+        void
+        ActiveOrTerminatedSkillStatusUpdate::fromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            SkillStatusUpdateBase::fromIce(update);
+            skills::fromIce(update.header.status, status);
+        }
+
+        void
+        ActiveOrTerminatedSkillStatusUpdate::fromIce(const provider::dto::SkillStatusUpdate& update,
+                                                     const std::string& providerName)
+        {
+            SkillStatusUpdateBase::fromIce(update, providerName);
+            skills::fromIce(update.header.status, status);
+        }
+
+        ActiveOrTerminatedSkillStatusUpdate
+        ActiveOrTerminatedSkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update)
+        {
+            ActiveOrTerminatedSkillStatusUpdate ret;
+            ret.fromIce(update);
             return ret;
         }
 
-        ActiveOrTerminatedSkillStatusUpdate ActiveOrTerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update)
+        ActiveOrTerminatedSkillStatusUpdate
+        ActiveOrTerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update,
+                                                     const std::string& providerName)
         {
             ActiveOrTerminatedSkillStatusUpdate ret;
-            ret.skillId = {update.header.skillId.providerName, update.header.skillId.skillName};
-            ret.executorName = update.header.executorName;
-            skills::fromIce(update.header.status, ret.status);
-            ret.usedParameterization = {aron::data::Dict::FromAronDictDTO(update.header.usedParams), update.header.usedCallbackInterface};
-            ret.data = aron::data::Dict::FromAronDictDTO(update.data);
+            ret.fromIce(update, providerName);
             return ret;
         }
-    }
-}
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h
index 6e1ec3c169c01d337ddb94f337414f2443d11ff8..246577de43f8958330f75e9d1669e60fb93e3ae5 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h
@@ -3,8 +3,11 @@
 #include <string>
 #include <vector>
 
-#include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
+#include <ArmarXCore/core/time/DateTime.h>
+#include <ArmarXCore/core/time/ice_conversions.h>
+
 #include <RobotAPI/interface/skills/SkillProviderInterface.h>
+#include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
 
 #include "SkillID.h"
 #include "SkillParameterization.h"
@@ -42,49 +45,144 @@ namespace armarx
         SkillStatus toSkillStatus(const TerminatedSkillStatus&);
 
         void toIce(provider::dto::Execution::Status& ret, const SkillStatus& status);
-        void toIce(provider::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status);
+        void toIce(provider::dto::Execution::Status& ret,
+                   const ActiveOrTerminatedSkillStatus& status);
         void toIce(provider::dto::Execution::Status& ret, const TerminatedSkillStatus& status);
 
         void fromIce(const provider::dto::Execution::Status& status, TerminatedSkillStatus& ret);
-        void fromIce(const provider::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret);
+        void fromIce(const provider::dto::Execution::Status& status,
+                     ActiveOrTerminatedSkillStatus& ret);
         void fromIce(const provider::dto::Execution::Status& status, SkillStatus& ret);
 
+        struct SkillExecutionId
+        {
+            static const constexpr char* NOT_INITIALIZED = "NOT INITIALIZED YET";
+            SkillID skillId = {NOT_INITIALIZED, NOT_INITIALIZED};
+            std::string executorName = "";
+            armarx::core::time::DateTime executionStartedTime =
+                armarx::core::time::DateTime::Invalid();
+
+            bool
+            operator==(const SkillExecutionId& other) const
+            {
+                if (skillId != other.skillId)
+                {
+                    return false;
+                }
+                if (executionStartedTime != other.executionStartedTime)
+                {
+                    return false;
+                }
+                if (executorName != other.executorName)
+                {
+                    return false;
+                }
+                return true;
+            }
+
+            bool
+            operator<(const SkillExecutionId& other) const
+            {
+                // We explicitly do not compare skillIds as we ONLY want to bring the executionids in some (temporal) order
+                return executionStartedTime < other.executionStartedTime;
+            }
+
+            skills::manager::dto::SkillExecutionID toIce() const;
+
+            skills::provider::dto::SkillExecutionID toIceProviderView() const;
+
+            void fromIce(const skills::manager::dto::SkillExecutionID&);
+
+            void fromIce(const skills::provider::dto::SkillExecutionID&,
+                         const std::string& providerName);
+
+            static SkillExecutionId FromIce(const skills::manager::dto::SkillExecutionID&);
+
+            static SkillExecutionId FromIce(const skills::provider::dto::SkillExecutionID&,
+                                            const std::string& providerName);
+        };
+
         struct SkillStatusUpdateBase
         {
             // header
-            SkillID                                             skillId = {"NOT INITIALIZED YET", "NOT INITIALIZED YET"};
-            std::string                                         executorName = "";
-            SkillParameterization                               usedParameterization;
+            SkillExecutionId executionId;
+            SkillParameterization usedParameterization;
 
             // data
-            aron::data::DictPtr                                 data = nullptr;
+            aron::data::DictPtr data = nullptr;
+
+            manager::dto::SkillStatusUpdate toIce() const;
+
+            provider::dto::SkillStatusUpdate toIceProviderView() const;
+
+            void fromIce(const provider::dto::SkillStatusUpdate& update,
+                         const std::string& providerName);
+
+            void fromIce(const manager::dto::SkillStatusUpdate& update);
         };
 
         // Will be returned after the execution of a skill
         struct TerminatedSkillStatusUpdate : public SkillStatusUpdateBase
         {
-            TerminatedSkillStatus                               status = TerminatedSkillStatus::Failed;
+            TerminatedSkillStatus status = TerminatedSkillStatus::Failed;
+
+            manager::dto::SkillStatusUpdate toIce() const;
+
+            provider::dto::SkillStatusUpdate toIceProviderView() const;
+
+            void fromIce(const provider::dto::SkillStatusUpdate& update,
+                         const std::string& providerName);
 
-            provider::dto::SkillStatusUpdate toIce() const;
-            static TerminatedSkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update);
+            void fromIce(const manager::dto::SkillStatusUpdate& update);
+
+            static TerminatedSkillStatusUpdate
+            FromIce(const provider::dto::SkillStatusUpdate& update,
+                    const std::string& providerName);
+
+            static TerminatedSkillStatusUpdate
+            FromIce(const manager::dto::SkillStatusUpdate& update);
         };
 
         // Will be returned from periodic skills which can still run
         struct ActiveOrTerminatedSkillStatusUpdate : public SkillStatusUpdateBase
         {
-            ActiveOrTerminatedSkillStatus                       status = ActiveOrTerminatedSkillStatus::Failed;
+            ActiveOrTerminatedSkillStatus status = ActiveOrTerminatedSkillStatus::Failed;
+
+            manager::dto::SkillStatusUpdate toIce() const;
+
+            provider::dto::SkillStatusUpdate toIceProviderView() const;
+
+            void fromIce(const provider::dto::SkillStatusUpdate& update,
+                         const std::string& providerName);
+
+            void fromIce(const manager::dto::SkillStatusUpdate& update);
 
-            provider::dto::SkillStatusUpdate toIce() const;
-            static ActiveOrTerminatedSkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update);
+            static ActiveOrTerminatedSkillStatusUpdate
+            FromIce(const provider::dto::SkillStatusUpdate& update,
+                    const std::string& providerName);
+
+            static ActiveOrTerminatedSkillStatusUpdate
+            FromIce(const manager::dto::SkillStatusUpdate& update);
         };
 
         // Will be used as status updates from skills to the callback interface
         struct SkillStatusUpdate : public SkillStatusUpdateBase
         {
-            SkillStatus                                         status = SkillStatus::Idle;
+            SkillStatus status = SkillStatus::Idle;
+
+            manager::dto::SkillStatusUpdate toIce() const;
+
+            provider::dto::SkillStatusUpdate toIceProviderView() const;
+
+            void fromIce(const provider::dto::SkillStatusUpdate& update,
+                         const std::string& providerName);
+
+            void fromIce(const manager::dto::SkillStatusUpdate& update);
+
+            static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update,
+                                             const std::string& providerName);
 
-            provider::dto::SkillStatusUpdate toIce() const;
-            static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update);
+            static SkillStatusUpdate FromIce(const manager::dto::SkillStatusUpdate& update);
         };
-    }
-}
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
index 81e91b131294d542c286659e0691056ea0bc0894..32f8358c25f19a17aab365d7bc080ece79d90041 100644
--- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
+++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
@@ -4,40 +4,45 @@ namespace armarx
 {
     namespace skills::detail
     {
-        SkillImplementationWrapper::SkillImplementationWrapper(std::unique_ptr<skills::Skill>&& skill) :
+        SkillImplementationWrapper::SkillImplementationWrapper(
+            std::unique_ptr<skills::Skill>&& skill) :
             skill(std::move(skill))
         {
             ARMARX_CHECK_NOT_NULL(this->skill);
         }
 
-        TerminatedSkillStatusUpdate SkillImplementationWrapper::setupAndExecuteSkill(const std::string& executorName, const skills::SkillParameterization parameterization)
+        TerminatedSkillStatusUpdate
+        SkillImplementationWrapper::setupAndExecuteSkill(
+            const std::string& executorName,
+            const skills::SkillParameterization parameterization)
         {
-            std::unique_lock l(executingMutex);
-
             const std::string skillName = skill->description.skillName;
             ARMARX_INFO_S << "Executing skill: " << skillName;
 
-            // reset execution params. This func is also used to clean up once this method returns
-            auto resetExecParam = [&](){
-                std::unique_lock l2(skillStatusMutex); // skill is not updating
-                //statusUpdate.status = skills::provider::dto::Execution::Status::Idle; I decided to not update the status to idle every time the skill stops.
-                statusUpdate.data = nullptr;
-                statusUpdate.executorName = "";
-            };
+            // we can safely assume that no two executions have the same timestamp
+            const skills::SkillExecutionId executionId = {
+                skill->getSkillId(), executorName, armarx::core::time::DateTime::Now()};
 
             // set params and setup variables
-            auto setExecParams = [&](){
-                std::lock_guard l(skillStatusMutex);
-                statusUpdate.usedParameterization = parameterization;
-                statusUpdate.executorName = executorName;
-            };
+            {
+                std::unique_lock l(skillStatusesMutex);
+                statusUpdates[executionId] =
+                    SkillStatusUpdate({{executionId, parameterization}, SkillStatus::Scheduled});
+            }
 
-            resetExecParam();
-            setExecParams();
+            // reset execution params. This func is also used to clean up once this method returns
+            auto tidyUpStatusUpdates = [&]()
+            {
+                std::unique_lock l2(skillStatusesMutex);
+                statusUpdates.erase(executionId);
+            };
 
-            auto& aron_params = parameterization.usedInputParams;
-            auto updateStatus = [&](const SkillStatus status, const aron::data::DictPtr& data = nullptr){
-                std::lock_guard l(skillStatusMutex);
+            const auto& aron_params = parameterization.usedInputParams;
+            auto updateStatus =
+                [&](const SkillStatus status, const aron::data::DictPtr& data = nullptr)
+            {
+                std::unique_lock l(skillStatusesMutex);
+                auto& statusUpdate = statusUpdates[executionId];
                 statusUpdate.status = status;
                 statusUpdate.data = data;
 
@@ -45,11 +50,13 @@ namespace armarx
 
                 if (callbackInterface)
                 {
-                    callbackInterface->updateStatusForSkill(statusUpdate.toIce());
+                    callbackInterface->updateStatusForSkill(statusUpdate.toIceProviderView(),
+                                                            skill->getSkillId().providerName);
                 }
             };
 
-            auto createErrorMessage = [](const std::string& message){
+            auto createErrorMessage = [](const std::string& message)
+            {
                 auto obj = aron::make_dict();
                 auto m = aron::make_string(message, aron::Path({"errormessage"}));
                 obj->addElement("errormessage", m);
@@ -59,37 +66,54 @@ namespace armarx
             // Check params
             if (skill->description.acceptedType && not(aron_params))
             {
-                std::string message = "SkillError 001: The Skill '" + skillName + "' requires a type but params are NULL.";
+                std::string message = "SkillError 001: The Skill '" + skillName +
+                                      "' requires a type but params are NULL.";
                 ARMARX_ERROR_S << message;
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
 
-            if (skill->description.acceptedType && aron_params && not(aron_params->fullfillsType(skill->description.acceptedType)))
+            if (skill->description.acceptedType && aron_params &&
+                not(aron_params->fullfillsType(skill->description.acceptedType)))
             {
-                std::string message = "SkillError 002: The Skill '" + skillName + "' has a type and got parameters but the input does not match the type.";
+                std::string message =
+                    "SkillError 002: The Skill '" + skillName +
+                    "' has a type and got parameters but the input does not match the type.";
                 ARMARX_ERROR_S << message;
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
 
             // Check if skill is available with the given parameterization
             try
             {
-                if (not skill->isSkillAvailable(Skill::InitInput{.executorName = executorName, .params = aron_params}))
+                if (not skill->isSkillAvailable(
+                        Skill::InitInput{.executorName = executorName, .params = aron_params}))
                 {
-                    std::string message = "SkillError 101: The Skill '" + skillName + "' is not available.";
+                    std::string message =
+                        "SkillError 101: The Skill '" + skillName + "' is not available.";
                     ARMARX_WARNING << message;
-                    resetExecParam();
-                    return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                    tidyUpStatusUpdates();
+                    return TerminatedSkillStatusUpdate(
+                        {{executionId, parameterization, createErrorMessage(message)},
+                         TerminatedSkillStatus::Failed});
                 }
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 101e: An error occured during the check whether skill '" + skillName + "' is available. The error was: " + GetHandledExceptionString();
+                std::string message =
+                    "SkillError 101e: An error occured during the check whether skill '" +
+                    skillName + "' is available. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
 
             // set scheduled
@@ -100,28 +124,39 @@ namespace armarx
             {
                 skill->resetSkill();
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 201e: An error occured during the reset of skill '" + skillName + "'. The error was: " + GetHandledExceptionString();
+                std::string message =
+                    "SkillError 201e: An error occured during the reset of skill '" + skillName +
+                    "'. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
 
                 updateStatus(SkillStatus::Failed);
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
 
             try
             {
                 skill->waitForDependenciesOfSkill();
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 301e: An error occured during waiting for skill dependencies of skill '" + skillName + "'. The error was: " + GetHandledExceptionString();
+                std::string message = "SkillError 301e: An error occured during waiting for skill "
+                                      "dependencies of skill '" +
+                                      skillName +
+                                      "'. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
 
                 updateStatus(SkillStatus::Failed);
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
 
             // execute. If the skill fails for some reason, from this point it will always execute its exit function.
@@ -133,55 +168,79 @@ namespace armarx
                 Skill::InitResult initRet = skill->initSkill({executorName, aron_params});
                 if (initRet.status != TerminatedSkillStatus::Succeeded)
                 {
-                    std::string message = "SkillError 401: The initialization of skill '" + skillName + "' did not succeed.";
-                    skill->exitSkill({executorName, aron_params}); // try to exit skill. Ignore return value
+                    std::string message = "SkillError 401: The initialization of skill '" +
+                                          skillName + "' did not succeed.";
+                    skill->exitSkill(
+                        {executorName, aron_params}); // try to exit skill. Ignore return value
 
                     updateStatus(skills::toSkillStatus(initRet.status));
-                    resetExecParam();
-                    return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, initRet.status});
+                    tidyUpStatusUpdates();
+                    return TerminatedSkillStatusUpdate(
+                        {{executionId, parameterization, createErrorMessage(message)},
+                         initRet.status});
                 }
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 401e: An error occured during the initialization of skill '" + skillName + "'. The error was: " + GetHandledExceptionString();
+                std::string message =
+                    "SkillError 401e: An error occured during the initialization of skill '" +
+                    skillName + "'. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
-                skill->exitSkill({executorName, aron_params}); // try to exit skill. Ignore return value
+                skill->exitSkill(
+                    {executorName, aron_params}); // try to exit skill. Ignore return value
 
                 updateStatus(SkillStatus::Failed);
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
+
             // Init succeeded!
 
 
             Skill::MainResult mainRet;
             try
             {
-                mainRet = skill->mainOfSkill({executorName, aron_params, [&updateStatus](const aron::data::DictPtr& update)
-                {
-                    // during execution the statusUpdate.status is always RUNNING
-                    updateStatus(SkillStatus::Running, update);
-                }});
+                mainRet = skill->mainOfSkill({executorName,
+                                              aron_params,
+                                              [&updateStatus](const aron::data::DictPtr& update)
+                                              {
+                                                  // during execution the statusUpdate.status is always RUNNING
+                                                  updateStatus(SkillStatus::Running, update);
+                                              }});
                 if (mainRet.status != TerminatedSkillStatus::Succeeded)
                 {
-                    std::string message = "SkillError 501: The main method of skill '" + skillName + "' did not succeed.";
-                    skill->exitSkill({executorName, aron_params}); // try to exit skill. Ignore return value
+                    std::string message = "SkillError 501: The main method of skill '" + skillName +
+                                          "' did not succeed.";
+                    skill->exitSkill(
+                        {executorName, aron_params}); // try to exit skill. Ignore return value
 
                     updateStatus(skills::toSkillStatus(mainRet.status));
-                    resetExecParam();
-                    return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, mainRet.status});
+                    tidyUpStatusUpdates();
+                    return TerminatedSkillStatusUpdate(
+                        {{executionId, parameterization, createErrorMessage(message)},
+                         mainRet.status});
                 }
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 501e: An error occured during the main method of skill '" + skillName + "'. The error was: " + GetHandledExceptionString();
+                std::string message =
+                    "SkillError 501e: An error occured during the main method of skill '" +
+                    skillName + "'. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
-                skill->exitSkill({executorName, aron_params}); // try to exit skill. Ignore return value
+                skill->exitSkill(
+                    {executorName, aron_params}); // try to exit skill. Ignore return value
 
                 updateStatus(SkillStatus::Failed);
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
+
             // Main succeeded!
 
             try
@@ -189,23 +248,33 @@ namespace armarx
                 Skill::ExitResult exitRet = skill->exitSkill({executorName, aron_params});
                 if (exitRet.status != TerminatedSkillStatus::Succeeded)
                 {
-                    std::string message = "SkillError 601: The exit method of skill '" + skillName + "' did not succeed.";
-                    skill->exitSkill({executorName, aron_params}); // try to exit skill. Ignore return value
+                    std::string message = "SkillError 601: The exit method of skill '" + skillName +
+                                          "' did not succeed.";
+                    skill->exitSkill(
+                        {executorName, aron_params}); // try to exit skill. Ignore return value
 
                     updateStatus(skills::toSkillStatus(exitRet.status));
-                    resetExecParam();
-                    return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, exitRet.status});
+                    tidyUpStatusUpdates();
+                    return TerminatedSkillStatusUpdate(
+                        {{executionId, parameterization, createErrorMessage(message)},
+                         exitRet.status});
                 }
             }
+
             catch (const std::exception& ex)
             {
-                std::string message = "SkillError 601e: An error occured during the exit method of skill '" + skillName + "'. The error was: " + GetHandledExceptionString();
+                std::string message =
+                    "SkillError 601e: An error occured during the exit method of skill '" +
+                    skillName + "'. The error was: " + GetHandledExceptionString();
                 ARMARX_ERROR_S << message;
 
                 updateStatus(SkillStatus::Failed);
-                resetExecParam();
-                return TerminatedSkillStatusUpdate({{skill->getSkillId(), executorName, parameterization, createErrorMessage(message)}, TerminatedSkillStatus::Failed});
+                tidyUpStatusUpdates();
+                return TerminatedSkillStatusUpdate(
+                    {{executionId, parameterization, createErrorMessage(message)},
+                     TerminatedSkillStatus::Failed});
             }
+
             // Exit succeeded!
 
 
@@ -213,10 +282,11 @@ namespace armarx
             updateStatus(SkillStatus::Succeeded);
 
             // Tidy up
-            resetExecParam();
+            tidyUpStatusUpdates();
 
             // return result of main method
-            return {{skill->getSkillId(), executorName, parameterization, mainRet.data}, TerminatedSkillStatus::Succeeded};
+            return {{executionId, parameterization, mainRet.data},
+                    TerminatedSkillStatus::Succeeded};
         }
-    }
-}
+    } // namespace skills::detail
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
index 982bcc366dd415ceb85ce055a35992ae99a8165f..32fafd3537724d96fde728e1ce3ddba5d2b06ad2 100644
--- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
+++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
@@ -2,11 +2,11 @@
 
 #include <shared_mutex>
 
+#include <RobotAPI/interface/skills/SkillManagerInterface.h>
+
+#include "../Skill.h"
 #include "../SkillDescription.h"
 #include "../SkillStatusUpdate.h"
-#include "../Skill.h"
-
-#include <RobotAPI/interface/skills/SkillManagerInterface.h>
 
 namespace armarx
 {
@@ -20,22 +20,20 @@ namespace armarx
                 // fixed values. Do not change after skill instantiation
                 const std::unique_ptr<Skill> skill;
 
-                // Current execution status. Changes during execution
+                // Current execution statuses. Changes during execution
                 // The status also holds the used parameterization
-                // skillName and providerName are const after registering the skill in a provider
-                mutable std::shared_mutex skillStatusMutex;
-                SkillStatusUpdate statusUpdate;
-
-                // Task information
-                mutable std::shared_mutex executingMutex;
+                mutable std::shared_mutex skillStatusesMutex;
+                std::map<skills::SkillExecutionId, SkillStatusUpdate> statusUpdates;
 
                 // ctor
                 SkillImplementationWrapper(std::unique_ptr<skills::Skill>&& skill);
 
                 // execute a skill. The parameterization is copied. T
                 // the return type additionally contains the input configuration (similar to the status updates used in callbacks)
-                TerminatedSkillStatusUpdate setupAndExecuteSkill(const std::string& executorName, const skills::SkillParameterization);
+                TerminatedSkillStatusUpdate
+                setupAndExecuteSkill(const std::string& executorName,
+                                     const skills::SkillParameterization);
             };
-        }
-    }
-}
+        } // namespace detail
+    } // namespace skills
+} // namespace armarx