diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
index 02cbe58cef253fc0d741c182caa32b7c3d2a529c..d77d737156239241ed8a62952e788da11c99bb55 100644
--- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
+++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp
@@ -156,6 +156,16 @@ namespace armarx
         return SkillManagerComponentPluginUser::executeSkill(info, current);
     }
 
+    skills::manager::dto::SkillExecutionID
+    SkillsMemory::executeSkillAsync(const skills::manager::dto::SkillExecutionRequest& info,
+                                    const Ice::Current& current)
+    {
+        auto e = skills::SkillExecutionRequest::FromIce(info);
+        skillExecutionRequestCoreSegment.addSkillExecutionRequest(e);
+
+        return SkillManagerComponentPluginUser::executeSkillAsync(info, current);
+    }
+
     void
     SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
                                        const skills::callback::dto::ProviderID& providerId,
@@ -166,14 +176,27 @@ namespace armarx
         skillEventCoreSegment.addSkillUpdateEvent(u);
     }
 
+    IceUtil::Optional<skills::manager::dto::SkillStatusUpdate>
+    SkillsMemory::getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId,
+                                          const Ice::Current& current)
+    {
+        auto eid = skills::SkillExecutionID::FromIce(executionId);
+        auto op = this->skillEventCoreSegment.getSkillStatusUpdate(eid);
+        if (op.has_value())
+        {
+            return op->toManagerIce();
+        }
+        return {};
+    }
+
     skills::manager::dto::SkillStatusUpdateMap
-    SkillsMemory::getLatestSkillExecutionStatuses(int n, const Ice::Current& current)
+    SkillsMemory::getSkillExecutionStatuses(const Ice::Current& current)
     {
-        auto m = skillEventCoreSegment.getLatestSkillEvents(n);
         skills::manager::dto::SkillStatusUpdateMap ret;
-        for (const auto& [k, v] : m)
+        auto updates = this->skillEventCoreSegment.getSkillStatusUpdates();
+        for (const auto& [k, v] : updates)
         {
-            ret[k.toManagerIce()] = v.toManagerIce();
+            ret.insert({k.toManagerIce(), v.toManagerIce()});
         }
         return ret;
     }
diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
index 81109b0bdf8787d6446e02fc11dcfe56ba484c4a..ead9f19122bc80266196aff40f138b4bd87c77f1 100644
--- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
+++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h
@@ -85,12 +85,21 @@ namespace armarx
         executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
                      const Ice::Current& current) override;
 
+
+        skills::manager::dto::SkillExecutionID
+        executeSkillAsync(const skills::manager::dto::SkillExecutionRequest& info,
+                          const Ice::Current& current) override;
+
         void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
                                   const skills::callback::dto::ProviderID& id,
                                   const Ice::Current& current) override;
 
+        IceUtil::Optional<skills::manager::dto::SkillStatusUpdate>
+        getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId,
+                                const Ice::Current& current) override;
+
         skills::manager::dto::SkillStatusUpdateMap
-        getLatestSkillExecutionStatuses(int n, const Ice::Current& current) override;
+        getSkillExecutionStatuses(const Ice::Current& current) override;
 
         // WritingInterface interface
         armem::data::CommitResult commit(const armem::data::Commit& commit,
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/CMakeLists.txt b/source/RobotAPI/components/skills/SkillProviderExample/CMakeLists.txt
index afbb7ef2abd07d6e718c7480ba7d84455574041d..b13f663e25b6c31fbb4ab3b919ce81431d617b70 100644
--- a/source/RobotAPI/components/skills/SkillProviderExample/CMakeLists.txt
+++ b/source/RobotAPI/components/skills/SkillProviderExample/CMakeLists.txt
@@ -13,10 +13,20 @@ set(COMPONENT_LIBS
 
 set(SOURCES
     SkillProviderExample.cpp
+    HelloWorld.cpp
+    Incomplete.cpp
+    Chaining.cpp
+    Callback.cpp
+    Timeout.cpp
 )
 
 set(HEADERS
     SkillProviderExample.h
+    HelloWorld.h
+    Incomplete.h
+    Chaining.h
+    Callback.h
+    Timeout.h
 )
 
 armarx_add_component("${SOURCES}" "${HEADERS}")
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Callback.cpp b/source/RobotAPI/components/skills/SkillProviderExample/Callback.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d13f3bb8df87414c8facac89adde3f587c34382c
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Callback.cpp
@@ -0,0 +1,39 @@
+
+#include "Callback.h"
+
+namespace armarx::skills::provider
+{
+    CallbackSkill::CallbackSkill() : SimpleSkill(GetSkillDescription())
+    {
+    }
+
+    SkillDescription
+    CallbackSkill::GetSkillDescription()
+    {
+        return SkillDescription{{"ShowMeCallbacks"},
+                                "This skill does shows callbacks",
+                                {},
+                                armarx::core::time::Duration::MilliSeconds(1000),
+                                nullptr};
+    }
+
+    Skill::MainResult
+    CallbackSkill::main(const MainInput& in)
+    {
+        ARMARX_IMPORTANT << "Logging three updates via the callback";
+        auto up1 = std::make_shared<aron::data::Dict>();
+        up1->addElement("updateInfo", std::make_shared<aron::data::String>("Update 1"));
+
+        in.callback(skills::SkillStatus::Running, up1);
+
+        auto up2 = std::make_shared<aron::data::Dict>();
+        up2->addElement("updateInfo", std::make_shared<aron::data::String>("Update 2"));
+        in.callback(skills::SkillStatus::Running, up2);
+
+        auto up3 = std::make_shared<aron::data::Dict>();
+        up3->addElement("updateInfo", std::make_shared<aron::data::String>("Update 3"));
+        in.callback(skills::SkillStatus::Running, up3);
+
+        return {TerminatedSkillStatus::Succeeded, nullptr};
+    }
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Callback.h b/source/RobotAPI/components/skills/SkillProviderExample/Callback.h
new file mode 100644
index 0000000000000000000000000000000000000000..c29c2b6f3d6007b1fda30b0c781b91be03a15232
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Callback.h
@@ -0,0 +1,41 @@
+
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+
+// RobotAPI
+#include <RobotAPI/libraries/skills/provider/SimpleSkill.h>
+
+namespace armarx::skills::provider
+{
+    class CallbackSkill : public SimpleSkill
+    {
+    public:
+        CallbackSkill();
+
+        static SkillDescription GetSkillDescription();
+
+    private:
+        Skill::MainResult main(const MainInput&) final;
+    };
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Chaining.cpp b/source/RobotAPI/components/skills/SkillProviderExample/Chaining.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c40b511a667ab4ea94647723c4532c64b115559a
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Chaining.cpp
@@ -0,0 +1,39 @@
+
+
+#include "Chaining.h"
+
+namespace armarx::skills::provider
+{
+
+    ChainingSkill::ChainingSkill() : SimpleSkill(GetSkillDescription())
+    {
+    }
+
+    SkillDescription
+    ChainingSkill::GetSkillDescription()
+    {
+        return SkillDescription{{"ChainingSkill"},
+                                "This skill calls the Timeout skill three times. The last "
+                                "execution is aborted due to a timeout of this skill.",
+                                {},
+                                armarx::core::time::Duration::MilliSeconds(5000),
+                                nullptr};
+    }
+
+    Skill::MainResult
+    ChainingSkill::main(const MainInput& in)
+    {
+        SkillProxy prx(manager, skills::SkillID(*getSkillId().providerId, "Timeout"));
+
+        ARMARX_INFO << "CALL PROXY FIRST TIME";
+        callSubskill(prx);
+        ARMARX_INFO << "CALL PROXY SECOND TIME";
+        callSubskill(prx);
+        ARMARX_INFO << "CALL PROXY THIRD TIME";
+        callSubskill(prx);
+
+        this->throwIfSkillShouldTerminate();
+
+        return {TerminatedSkillStatus::Succeeded, nullptr};
+    }
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Chaining.h b/source/RobotAPI/components/skills/SkillProviderExample/Chaining.h
new file mode 100644
index 0000000000000000000000000000000000000000..991c4a5aaab5d1be83f9684ca5bdbca1638b946d
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Chaining.h
@@ -0,0 +1,40 @@
+
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+// RobotAPI
+#include <RobotAPI/libraries/skills/provider/SimpleSkill.h>
+
+namespace armarx::skills::provider
+{
+    class ChainingSkill : public SimpleSkill
+    {
+    public:
+        ChainingSkill();
+
+        static SkillDescription GetSkillDescription();
+
+    private:
+        Skill::MainResult main(const MainInput&) final;
+    };
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.cpp b/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccfa7f31a5e4dd7a235f1ef1d60a441441a8a595
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.cpp
@@ -0,0 +1,49 @@
+
+
+#include "HelloWorld.h"
+
+#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
+#include <RobotAPI/libraries/aron/core/type/variant/container/Object.h>
+#include <RobotAPI/libraries/aron/core/type/variant/primitive/String.h>
+
+namespace armarx::skills::provider
+{
+    HelloWorldSkill::HelloWorldSkill() :
+        SimpleSpecializedSkill<skills::Example::HelloWorldAcceptedType>(GetSkillDescription())
+    {
+    }
+
+    SkillDescription
+    HelloWorldSkill::GetSkillDescription()
+    {
+        armarx::skills::Example::HelloWorldAcceptedType root_profile_params;
+        root_profile_params.some_float = 5;
+        root_profile_params.some_int = 42;
+        root_profile_params.some_text = "YOLO";
+        root_profile_params.some_list_of_matrices.push_back(Eigen::Matrix3f::Zero());
+        root_profile_params.some_matrix = Eigen::Matrix3f::Zero();
+
+        return SkillDescription{{"HelloWorld"},
+                                "This skill logs a message on ARMARX_IMPORTANT",
+                                root_profile_params.toAron(),
+                                armarx::core::time::Duration::MilliSeconds(1000),
+                                armarx::skills::Example::HelloWorldAcceptedType::ToAronType()};
+    }
+
+    Skill::MainResult
+    HelloWorldSkill::main(const SpecializedMainInput& in)
+    {
+        ARMARX_IMPORTANT << "Hi, from the Hello World Skill.\n"
+                         << "I received the following data: \n"
+                         << aron::data::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(
+                                in.parameters.toAron())
+                                .dump(2)
+                         << "\n"
+                         << "Type fulfilled? "
+                         << parameters->fullfillsType(
+                                armarx::skills::Example::HelloWorldAcceptedType::ToAronType())
+                         << "\n"
+                         << "(executed at: " << IceUtil::Time::now() << ")";
+        return {TerminatedSkillStatus::Succeeded, nullptr};
+    }
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.h b/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.h
new file mode 100644
index 0000000000000000000000000000000000000000..840b058fb171685db777126157fc21028db89c99
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/HelloWorld.h
@@ -0,0 +1,42 @@
+
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+// RobotAPI
+#include <RobotAPI/components/skills/SkillProviderExample/aron/HelloWorldAcceptedType.aron.generated.h>
+#include <RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h>
+
+namespace armarx::skills::provider
+{
+    // Skills:
+    class HelloWorldSkill : public SimpleSpecializedSkill<skills::Example::HelloWorldAcceptedType>
+    {
+    public:
+        HelloWorldSkill();
+
+        static SkillDescription GetSkillDescription();
+
+    private:
+        Skill::MainResult main(const SpecializedMainInput& in) final;
+    };
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.cpp b/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac9bf9af3d980d76695ae64176c60d063a440263
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.cpp
@@ -0,0 +1,55 @@
+
+
+#include "Incomplete.h"
+
+#include <RobotAPI/components/skills/SkillProviderExample/aron/HelloWorldAcceptedType.aron.generated.h>
+
+#include "HelloWorld.h"
+
+namespace armarx::skills::provider
+{
+
+    IncompleteSkill::IncompleteSkill() : SimpleSkill(GetSkillDescription())
+    {
+    }
+
+    SkillDescription
+    IncompleteSkill::GetSkillDescription()
+    {
+        auto d = HelloWorldSkill::GetSkillDescription();
+        return SkillDescription{{"IncompleteSkill"},
+                                d.description,
+                                {},
+                                d.timeout + armarx::core::time::Duration::Seconds(2),
+                                d.parametersType};
+    }
+
+    Skill::PrepareResult
+    IncompleteSkill::prepare()
+    {
+        if (!first_prepared)
+        {
+            first_prepared = true;
+
+            // set parameters after two seconds...
+            std::thread foo(
+                [&]()
+                {
+                    auto d = HelloWorldSkill::GetSkillDescription();
+                    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+                    this->setParameters(d.rootProfileDefaults);
+                });
+            foo.detach();
+        }
+
+        return {.status = ActiveOrTerminatedSkillStatus::Succeeded};
+    }
+
+    Skill::MainResult
+    IncompleteSkill::main(const MainInput& in)
+    {
+        auto s = HelloWorldSkill();
+        s.setParameters(in.parameters);
+        return s.mainOfSkill();
+    }
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.h b/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.h
new file mode 100644
index 0000000000000000000000000000000000000000..6cf7b6e73b597b201d9d5213db160151d3a971c8
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Incomplete.h
@@ -0,0 +1,44 @@
+
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+// RobotAPI
+#include <RobotAPI/libraries/skills/provider/SimpleSkill.h>
+
+namespace armarx::skills::provider
+{
+
+    class IncompleteSkill : public SimpleSkill
+    {
+    public:
+        IncompleteSkill();
+
+        static SkillDescription GetSkillDescription();
+
+    private:
+        Skill::PrepareResult prepare() final;
+        Skill::MainResult main(const MainInput&) final;
+
+        std::atomic_bool first_prepared = false;
+    };
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
index 4e82f6d7e1408170e7d992996cebcba7d56e7fbb..4230249f7d9eb30ca641da0bbd5f2934c2307d48 100644
--- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
+++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
@@ -1,192 +1,8 @@
 
-
 #include "SkillProviderExample.h"
 
-#include <RobotAPI/components/skills/SkillProviderExample/aron/HelloWorldAcceptedType.aron.generated.h>
-#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
-#include <RobotAPI/libraries/aron/core/type/variant/container/Object.h>
-#include <RobotAPI/libraries/aron/core/type/variant/primitive/String.h>
-
 namespace armarx::skills::provider
 {
-    HelloWorldSkill::HelloWorldSkill() :
-        SimpleSpecializedSkill<skills::Example::HelloWorldAcceptedType>(GetSkillDescription())
-    {
-    }
-
-    SkillDescription
-    HelloWorldSkill::GetSkillDescription()
-    {
-        armarx::skills::Example::HelloWorldAcceptedType root_profile_params;
-        root_profile_params.some_float = 5;
-        root_profile_params.some_int = 42;
-        root_profile_params.some_text = "YOLO";
-        root_profile_params.some_list_of_matrices.push_back(Eigen::Matrix3f::Zero());
-        root_profile_params.some_matrix = Eigen::Matrix3f::Zero();
-
-        return SkillDescription{{"HelloWorld"},
-                                "This skill logs a message on ARMARX_IMPORTANT",
-                                root_profile_params.toAron(),
-                                armarx::core::time::Duration::MilliSeconds(1000),
-                                armarx::skills::Example::HelloWorldAcceptedType::ToAronType()};
-    }
-
-    Skill::MainResult
-    HelloWorldSkill::main(const SpecializedMainInput& in)
-    {
-        ARMARX_IMPORTANT << "Hi, from the Hello World Skill.\n"
-                         << "I received the following data: \n"
-                         << aron::data::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(
-                                in.parameters.toAron())
-                                .dump(2)
-                         << "\n"
-                         << "Type fulfilled? "
-                         << parameters->fullfillsType(
-                                armarx::skills::Example::HelloWorldAcceptedType::ToAronType())
-                         << "\n"
-                         << "(executed at: " << IceUtil::Time::now() << ")";
-        return {TerminatedSkillStatus::Succeeded, nullptr};
-    }
-
-    IncompleteSkill::IncompleteSkill() : SimpleSkill(GetSkillDescription())
-    {
-    }
-
-    SkillDescription
-    IncompleteSkill::GetSkillDescription()
-    {
-        auto d = HelloWorldSkill::GetSkillDescription();
-        return SkillDescription{{"IncompleteSkill"},
-                                d.description,
-                                {},
-                                d.timeout + armarx::core::time::Duration::Seconds(2),
-                                d.parametersType};
-    }
-
-    Skill::PrepareResult
-    IncompleteSkill::prepare()
-    {
-        if (!first_prepared)
-        {
-            first_prepared = true;
-            std::thread foo(
-                [&]()
-                {
-                    auto d = HelloWorldSkill::GetSkillDescription();
-                    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
-                    this->setParameters(d.rootProfileDefaults);
-                });
-            foo.detach();
-        }
-
-        auto s = HelloWorldSkill();
-        s.setParameters(this->getParameters());
-        s.mainOfSkill();
-
-        return {.status = ActiveOrTerminatedSkillStatus::Succeeded};
-    }
-
-    Skill::MainResult
-    IncompleteSkill::main(const MainInput& in)
-    {
-        auto s = HelloWorldSkill();
-        s.setParameters(in.parameters);
-        return s.mainOfSkill();
-    }
-
-    ChainingSkill::ChainingSkill() : SimpleSkill(GetSkillDescription())
-    {
-    }
-
-    SkillDescription
-    ChainingSkill::GetSkillDescription()
-    {
-        return SkillDescription{{"ChainingSkill"},
-                                "This skill calls the HelloWorld skill three times.",
-                                {},
-                                armarx::core::time::Duration::MilliSeconds(3000),
-                                nullptr};
-    }
-
-    Skill::MainResult
-    ChainingSkill::main(const MainInput& in)
-    {
-        armarx::skills::Example::HelloWorldAcceptedType exec1;
-        armarx::skills::Example::HelloWorldAcceptedType exec2;
-        armarx::skills::Example::HelloWorldAcceptedType exec3;
-
-        exec1.some_text = "Hello from the ChainingSkill 1";
-        exec2.some_text = "Hello from the ChainingSkill 2";
-        exec3.some_text = "Hello from the ChainingSkill 3";
-
-        SkillProxy skillExecPrx(
-            manager, skills::SkillID(skills::ProviderID("SkillProviderExample"), "HelloWorld"));
-
-        skillExecPrx.executeSkill(getSkillId().toString(), exec1.toAron());
-        skillExecPrx.executeSkill(getSkillId().toString(), exec2.toAron());
-        skillExecPrx.executeSkill(getSkillId().toString(), exec3.toAron());
-
-        return {TerminatedSkillStatus::Succeeded, nullptr};
-    }
-
-    TimeoutSkill::TimeoutSkill() :
-        PeriodicSkill(GetSkillDescription(), armarx::core::time::Frequency::Hertz(5))
-    {
-    }
-
-    SkillDescription
-    TimeoutSkill::GetSkillDescription()
-    {
-        return SkillDescription{{"Timeout"},
-                                "This fails with timeout reached",
-                                {},
-                                armarx::core::time::Duration::MilliSeconds(5000),
-                                nullptr};
-    }
-
-    PeriodicSkill::StepResult
-    TimeoutSkill::step()
-    {
-        // do heavy work
-        std::this_thread::sleep_for(std::chrono::milliseconds(500));
-
-        return {ActiveOrTerminatedSkillStatus::Running, nullptr};
-    }
-
-    CallbackSkill::CallbackSkill() : SimpleSkill(GetSkillDescription())
-    {
-    }
-
-    SkillDescription
-    CallbackSkill::GetSkillDescription()
-    {
-        return SkillDescription{{"ShowMeCallbacks"},
-                                "This skill does shows callbacks",
-                                {},
-                                armarx::core::time::Duration::MilliSeconds(1000),
-                                nullptr};
-    }
-
-    Skill::MainResult
-    CallbackSkill::main(const MainInput& in)
-    {
-        ARMARX_IMPORTANT << "Logging three updates via the callback";
-        auto up1 = std::make_shared<aron::data::Dict>();
-        up1->addElement("updateInfo", std::make_shared<aron::data::String>("Update 1"));
-
-        in.callback(skills::SkillStatus::Running, up1);
-
-        auto up2 = std::make_shared<aron::data::Dict>();
-        up2->addElement("updateInfo", std::make_shared<aron::data::String>("Update 2"));
-        in.callback(skills::SkillStatus::Running, up2);
-
-        auto up3 = std::make_shared<aron::data::Dict>();
-        up3->addElement("updateInfo", std::make_shared<aron::data::String>("Update 3"));
-        in.callback(skills::SkillStatus::Running, up3);
-
-        return {TerminatedSkillStatus::Succeeded, nullptr};
-    }
-
     SkillProviderExample::SkillProviderExample() : SkillProviderComponentPluginUser()
     {
     }
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h
index 24d607450191b6ab98f3ba45112a417337358308..b8391b0881f625af03b00b601983251c4d90558b 100644
--- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h
+++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h
@@ -27,73 +27,16 @@
 #include <ArmarXCore/core/Component.h>
 
 // RobotAPI
-#include <RobotAPI/components/skills/SkillProviderExample/aron/HelloWorldAcceptedType.aron.generated.h>
-#include <RobotAPI/libraries/skills/provider/SimpleSkill.h>
-#include <RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h>
 #include <RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h>
-#include <RobotAPI/libraries/skills/provider/SkillProxy.h>
+
+#include "Callback.h"
+#include "Chaining.h"
+#include "HelloWorld.h"
+#include "Incomplete.h"
+#include "Timeout.h"
 
 namespace armarx::skills::provider
 {
-    // Skills:
-    class HelloWorldSkill : public SimpleSpecializedSkill<skills::Example::HelloWorldAcceptedType>
-    {
-    public:
-        HelloWorldSkill();
-
-        static SkillDescription GetSkillDescription();
-
-    private:
-        Skill::MainResult main(const SpecializedMainInput& in) final;
-    };
-
-    class IncompleteSkill : public SimpleSkill
-    {
-    public:
-        IncompleteSkill();
-
-        static SkillDescription GetSkillDescription();
-
-    private:
-        Skill::PrepareResult prepare() final;
-        Skill::MainResult main(const MainInput&) final;
-
-        std::atomic_bool first_prepared = false;
-    };
-
-    class ChainingSkill : public SimpleSkill
-    {
-    public:
-        ChainingSkill();
-
-        static SkillDescription GetSkillDescription();
-
-    private:
-        Skill::MainResult main(const MainInput&) final;
-    };
-
-    class TimeoutSkill : public PeriodicSkill
-    {
-    public:
-        TimeoutSkill();
-
-        static SkillDescription GetSkillDescription();
-
-    private:
-        PeriodicSkill::StepResult step() final;
-    };
-
-    class CallbackSkill : public SimpleSkill
-    {
-    public:
-        CallbackSkill();
-
-        static SkillDescription GetSkillDescription();
-
-    private:
-        Skill::MainResult main(const MainInput&) final;
-    };
-
     /**
      * @defgroup Component-ExampleClient ExampleClient
      * @ingroup RobotAPI-Components
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Timeout.cpp b/source/RobotAPI/components/skills/SkillProviderExample/Timeout.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..270dae01909e9bf0261b222257d22c4aec38a1ea
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Timeout.cpp
@@ -0,0 +1,30 @@
+
+#include "Timeout.h"
+
+namespace armarx::skills::provider
+{
+
+    TimeoutSkill::TimeoutSkill() :
+        PeriodicSkill(GetSkillDescription(), armarx::core::time::Frequency::Hertz(5))
+    {
+    }
+
+    SkillDescription
+    TimeoutSkill::GetSkillDescription()
+    {
+        return SkillDescription{{"Timeout"},
+                                "This fails with timeout reached",
+                                {},
+                                armarx::core::time::Duration::MilliSeconds(2000),
+                                nullptr};
+    }
+
+    PeriodicSkill::StepResult
+    TimeoutSkill::step()
+    {
+        // do heavy work
+        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+        return {ActiveOrTerminatedSkillStatus::Running, nullptr};
+    }
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/components/skills/SkillProviderExample/Timeout.h b/source/RobotAPI/components/skills/SkillProviderExample/Timeout.h
new file mode 100644
index 0000000000000000000000000000000000000000..347e216a956c22d8d38b3b0b434ec0b5f4cf0225
--- /dev/null
+++ b/source/RobotAPI/components/skills/SkillProviderExample/Timeout.h
@@ -0,0 +1,42 @@
+
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+
+// RobotAPI
+#include <RobotAPI/libraries/skills/provider/PeriodicSkill.h>
+
+namespace armarx::skills::provider
+{
+
+    class TimeoutSkill : public PeriodicSkill
+    {
+    public:
+        TimeoutSkill();
+
+        static SkillDescription GetSkillDescription();
+
+    private:
+        PeriodicSkill::StepResult step() final;
+    };
+} // namespace armarx::skills::provider
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
index b7880b87f624a20617e9d95738baf41c42620385..87450efc502a8430bffab8d205e0e3eec2dbbcb0 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
@@ -356,8 +356,9 @@ namespace armarx
         {
             std::scoped_lock l(updateMutex);
 
-            auto currentManagerStatuses = memory->getLatestSkillExecutionStatuses(
-                100); // we assume that there are no more than 100 new skills..
+            auto currentManagerStatuses =
+                memory
+                    ->getSkillExecutionStatuses(); // we assume that there are no more than 100 new skills..
 
             for (const auto& [k, v] : currentManagerStatuses)
             {
@@ -378,19 +379,19 @@ namespace armarx
                         // update values
                         found->setText(3,
                                        QString::fromStdString(
-                                           statusUpdate.hasBeenConstructed() ? " (\xfb) " : ""));
+                                           statusUpdate.hasBeenConstructed() ? " yes " : " no "));
                         found->setText(4,
                                        QString::fromStdString(
-                                           statusUpdate.hasBeenInitialized() ? " (\xfb) " : ""));
+                                           statusUpdate.hasBeenInitialized() ? " yes " : " no "));
                         found->setText(5,
                                        QString::fromStdString(
-                                           statusUpdate.hasBeenPrepared() ? " (\xfb) " : ""));
+                                           statusUpdate.hasBeenPrepared() ? " yes " : " no "));
                         found->setText(6,
                                        QString::fromStdString(
-                                           statusUpdate.hasBeenRunning() ? " (\xfb) " : ""));
+                                           statusUpdate.hasBeenRunning() ? " yes " : " no "));
                         found->setText(7,
                                        QString::fromStdString(
-                                           statusUpdate.hasBeenTerminated() ? " (\xfb) " : ""));
+                                           statusUpdate.hasBeenTerminated() ? " yes " : " no "));
                         break;
                     }
                 }
@@ -408,18 +409,19 @@ namespace armarx
                     item->setText(2, QString::fromStdString(executionId.skillId.toString()));
                     item->setText(3,
                                   QString::fromStdString(
-                                      statusUpdate.hasBeenConstructed() ? " (\xfb) " : ""));
+                                      statusUpdate.hasBeenConstructed() ? " yes " : " no "));
                     item->setText(4,
                                   QString::fromStdString(
-                                      statusUpdate.hasBeenInitialized() ? " (\xfb) " : ""));
+                                      statusUpdate.hasBeenInitialized() ? " yes " : " no "));
                     item->setText(
                         5,
-                        QString::fromStdString(statusUpdate.hasBeenPrepared() ? " (\xfb) " : ""));
+                        QString::fromStdString(statusUpdate.hasBeenPrepared() ? " yes " : " no "));
                     item->setText(
-                        6, QString::fromStdString(statusUpdate.hasBeenRunning() ? " (\xfb) " : ""));
-                    item->setText(
-                        7,
-                        QString::fromStdString(statusUpdate.hasBeenTerminated() ? " (\xfb) " : ""));
+                        6,
+                        QString::fromStdString(statusUpdate.hasBeenRunning() ? " yes " : " no "));
+                    item->setText(7,
+                                  QString::fromStdString(
+                                      statusUpdate.hasBeenTerminated() ? " yes " : " no "));
                 }
             }
         }
diff --git a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
index 934d2fabaf539697a8416f4567c734e36de25858..3d0d8ee61b23a5e184514b87792323d379c81173 100644
--- a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
+++ b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice
@@ -36,11 +36,7 @@ module armarx
         module dti
         {
             interface SkillMemoryInterface extends armem::server::MemoryInterface,
-                dti::StatechartListenerInterface, manager::dti::SkillManagerInterface
-            {
-                manager::dto::SkillStatusUpdateMap getLatestSkillExecutionStatuses(
-                    int n); // returns latest n statusupdates of all providers
-            };
+                dti::StatechartListenerInterface, manager::dti::SkillManagerInterface{};
         }
     }
 }
diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
index d50fcba804fd4d498fb1a0f0974c9057b1ae3ae9..11dc8d0dfb40953de6acc8f81921884808339376 100644
--- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
+++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp
@@ -53,39 +53,58 @@ namespace armarx::skills::segment
     }
 
     std::map<skills::SkillExecutionID, skills::SkillStatusUpdate>
-    SkillEventCoreSegment::getLatestSkillEvents(int n)
+    SkillEventCoreSegment::getSkillStatusUpdates()
     {
         std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> ret;
         auto coreSegment = this->segmentPtr;
         ARMARX_CHECK(coreSegment);
 
-        // 1. get all events and sort them by timestamp.
-        std::vector<skills::SkillStatusUpdate> sorted;
         coreSegment->forEachInstance(
-            [&sorted](const armem::wm::EntityInstance& i)
+            [&](const armem::wm::EntityInstance& i)
             {
                 auto event = i.dataAs<armarx::skills::arondto::SkillStatusUpdate>();
                 skills::SkillStatusUpdate up;
                 armem::fromAron(event, up);
-                sorted.emplace_back(std::move(up));
+
+                if (auto it = ret.find(up.executionId); it != ret.end() && up < it->second)
+                {
+                    return;
+                }
+
+                // set or replace
+                ret[up.executionId] = up;
             });
 
-        std::sort(sorted.begin(),
-                  sorted.end(),
-                  [](const skills::SkillStatusUpdate& a, const skills::SkillStatusUpdate& b)
-                  { return b < a; });
+        //        for (const auto& [k, v] : ret)
+        //        {
+        //            ARMARX_IMPORTANT << "Skill " << k.skillId << " has stati: " << int(v.status);
+        //        }
 
-        for (const auto& el : sorted)
-        {
-            if (ret.size() >= (size_t)n)
-            {
-                break;
-            }
+        return ret;
+    }
 
-            ret.emplace(
-                std::piecewise_construct, std::make_tuple(el.executionId), std::make_tuple(el));
-        }
+    std::optional<skills::SkillStatusUpdate>
+    SkillEventCoreSegment::getSkillStatusUpdate(const skills::SkillExecutionID& id)
+    {
+        std::optional<skills::SkillStatusUpdate> ret = std::nullopt;
+        auto coreSegment = this->segmentPtr;
+        ARMARX_CHECK(coreSegment);
 
+        coreSegment->forEachInstance(
+            [&](const armem::wm::EntityInstance& i)
+            {
+                auto event = i.dataAs<armarx::skills::arondto::SkillStatusUpdate>();
+                skills::SkillStatusUpdate up;
+                armem::fromAron(event, up);
+
+                if (up.executionId == id)
+                {
+                    if (!ret || (ret.has_value() && *ret < up))
+                    {
+                        ret = up;
+                    }
+                }
+            });
         return ret;
     }
 } // 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 492c26090479a2be9c80442aeddc814378975486..0537cbdbdf97d80649e10baa30786d2d1fb5870c 100644
--- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h
+++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h
@@ -27,7 +27,10 @@ namespace armarx::skills::segment
 
         void addSkillUpdateEvent(const skills::SkillStatusUpdate& update);
 
-        std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> getLatestSkillEvents(int n);
+        std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> getSkillStatusUpdates();
+
+        std::optional<skills::SkillStatusUpdate>
+        getSkillStatusUpdate(const skills::SkillExecutionID& id);
 
     private:
     };
diff --git a/source/RobotAPI/libraries/skills/core/CMakeLists.txt b/source/RobotAPI/libraries/skills/core/CMakeLists.txt
index 66795b7ecdf0b0aa0897a07f5e47e5f5d489d4a1..29145e60e305fa10decf06200685dcb99ec6a3d5 100644
--- a/source/RobotAPI/libraries/skills/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills/core/CMakeLists.txt
@@ -24,6 +24,7 @@ armarx_add_library(
         SkillPreparationInput.cpp
         SkillParameterization.cpp
         Skill.cpp
+        SkillProxy.cpp
         SkillDescription.cpp
     HEADERS
         error/Exception.h
@@ -36,6 +37,7 @@ armarx_add_library(
         SkillPreparationInput.h
         SkillParameterization.h
         Skill.h
+        SkillProxy.h
         SkillDescription.h
 )
 
diff --git a/source/RobotAPI/libraries/skills/core/Skill.cpp b/source/RobotAPI/libraries/skills/core/Skill.cpp
index 7d8d9b9c8c59c4476e7f5b2872cd5967972a65cb..34895c9066ca7202bb6e96c2885869f22ec26875 100644
--- a/source/RobotAPI/libraries/skills/core/Skill.cpp
+++ b/source/RobotAPI/libraries/skills/core/Skill.cpp
@@ -14,16 +14,76 @@ namespace armarx
         void
         Skill::installConditionWithCallback(std::function<bool()>&& f, std::function<void()>&& cb)
         {
-            std::lock_guard l(conditionCallbacksMutex);
+            std::scoped_lock l(conditionCallbacksMutex);
             conditionCallbacks.push_back({f, cb});
         }
 
+        std::optional<TerminatedSkillStatusUpdate>
+        Skill::callSubskill(const SkillProxy& prx, const aron::data::DictPtr& params)
+        {
+            auto eid = callSubskillAsync(prx, params);
+            auto ret = prx.join(eid);
+            ARMARX_IMPORTANT << "FINISHED SUBSKILL. RET IS " << ret.has_value();
+            return ret;
+        }
+
+        skills::SkillExecutionID
+        Skill::callSubskillAsync(const skills::SkillProxy& prx, const aron::data::DictPtr& params)
+        {
+            std::unique_lock l(subskillsMutex);
+
+            std::string executorHistory = this->executorName + "->" + getSkillId().toString();
+            auto eid = prx.executeSkillAsync(executorHistory, params);
+            this->subskills.push_back(eid);
+            return eid;
+        }
+
+        void
+        Skill::updateParameters(const aron::data::DictPtr& d)
+        {
+            std::scoped_lock l(this->parametersMutex);
+            if (this->parameters == nullptr)
+            {
+                // set params as there has been no update before.
+                this->parameters = d;
+            }
+            else
+            {
+                // merge params into existing. Note that this may update already set params.
+                this->parameters->mergeAndReplaceCopy(d);
+            }
+        }
+
+        void
+        Skill::setParameters(const aron::data::DictPtr& d)
+        {
+            // we only set the params if the skill is not already running
+            if (running or exiting or finished)
+            {
+                return;
+            }
+
+            std::scoped_lock l(this->parametersMutex);
+            this->parameters = d;
+        }
+
+        aron::data::DictPtr
+        Skill::getParameters() const
+        {
+            std::scoped_lock l(this->parametersMutex);
+            return this->parameters;
+        }
+
         Skill::InitResult
         Skill::_init()
         {
             //ARMARX_IMPORTANT << "Initializing skill '" << description.skillName << "'";
             this->initializing = true;
             this->constructing = false;
+            this->preparing = false;
+            this->running = false;
+            this->exiting = false;
+            this->finished = false;
 
             // install timeout condition
             installConditionWithCallback(
@@ -36,7 +96,7 @@ namespace armarx
                 [&]()
                 {
                     armarx::core::time::Metronome metronome(conditionCheckingThreadFrequency);
-                    while (constructing or initializing or preparing or
+                    while (initializing or preparing or
                            running) // when the skill ends/aborts this variable will be set to false
                     {
                         {
@@ -51,13 +111,15 @@ namespace armarx
                                 }
                             }
                         }
+
                         const auto sleepDuration = metronome.waitForNextTick();
                         if (not sleepDuration.isPositive())
                         {
-                            ARMARX_WARNING
-                                << deactivateSpam() << "PeriodicSkill: execution took too long ("
-                                << -sleepDuration << " vs "
-                                << conditionCheckingThreadFrequency.toCycleDuration() << ")";
+                            ARMARX_WARNING << deactivateSpam()
+                                           << "ConditionCheckingThread: execution took too long ("
+                                           << -sleepDuration << " vs "
+                                           << conditionCheckingThreadFrequency.toCycleDuration()
+                                           << ")";
                         }
                     }
                 });
@@ -69,6 +131,10 @@ namespace armarx
         {
             this->preparing = true;
             this->initializing = false;
+            this->constructing = false;
+            this->running = false;
+            this->exiting = false;
+            this->finished = false;
 
             if (shouldSkillTerminate())
             {
@@ -94,7 +160,11 @@ namespace armarx
         Skill::_main()
         {
             this->running = true;
+            this->initializing = false;
+            this->constructing = false;
             this->preparing = false;
+            this->exiting = false;
+            this->finished = false;
             return {.status = TerminatedSkillStatus::Succeeded};
         }
 
@@ -102,16 +172,21 @@ namespace armarx
         Skill::_exit()
         {
             // ARMARX_IMPORTANT << "Exiting Skill '" << description.skillName << "'";
+            this->exiting = true;
             this->running = false;
             this->initializing = false;
             this->constructing = false;
             this->preparing = false;
+            this->finished = false;
 
             if (conditionCheckingThread.joinable())
             {
                 conditionCheckingThread.join();
             }
             exited = armarx::core::time::DateTime::Now();
+
+            this->finished = true;
+            this->exiting = false;
             return {.status = TerminatedSkillStatus::Succeeded};
         }
 
@@ -152,13 +227,6 @@ namespace armarx
             return {.status = skills::mergeSkillStatuseses(_res.status, res.status)};
         }
 
-        void
-        Skill::notifyTimeoutReached()
-        {
-            timeoutReached = true;
-            onTimeoutReached();
-        }
-
         void
         Skill::throwIfSkillShouldTerminate(const std::function<void()>& do_before,
                                            const std::string& abortedMessage)
@@ -224,10 +292,21 @@ namespace armarx
         void
         Skill::notifySkillToStop()
         {
+            std::scoped_lock l(subskillsMutex);
             stopped = true;
+            _onStopRequested();
             onStopRequested();
         }
 
+        void
+        Skill::notifyTimeoutReached()
+        {
+            std::scoped_lock l(subskillsMutex);
+            timeoutReached = true;
+            _onTimeoutReached();
+            onTimeoutReached();
+        }
+
         bool
         Skill::shouldSkillTerminate() const
         {
@@ -235,6 +314,32 @@ namespace armarx
         }
 
         // condition effects
+        void
+        Skill::_onTimeoutReached()
+        {
+            if (!manager)
+            {
+                return;
+            }
+            for (const auto& execId : subskills)
+            {
+                manager->abortSkillAsync(execId.toManagerIce());
+            }
+        }
+
+        void
+        Skill::_onStopRequested()
+        {
+            if (!manager)
+            {
+                return;
+            }
+            for (const auto& execId : subskills)
+            {
+                manager->abortSkillAsync(execId.toManagerIce());
+            }
+        }
+
         void
         Skill::onTimeoutReached()
         {
diff --git a/source/RobotAPI/libraries/skills/core/Skill.h b/source/RobotAPI/libraries/skills/core/Skill.h
index ff3cf1e823a9bdcf2e8b4db8b68232a1b4a34cbe..5ec80e77d9956e8516ae84ffec16313bab0c9206 100644
--- a/source/RobotAPI/libraries/skills/core/Skill.h
+++ b/source/RobotAPI/libraries/skills/core/Skill.h
@@ -19,6 +19,7 @@
 #include "SkillDescription.h"
 #include "SkillID.h"
 #include "SkillPreparationInput.h"
+#include "SkillProxy.h"
 #include "SkillStatusUpdate.h"
 #include "error/Exception.h"
 
@@ -32,95 +33,112 @@ namespace armarx
             using CallbackT =
                 std::function<void(const SkillStatus s, const armarx::aron::data::DictPtr&)>;
 
+            /// A result struct for skill initialization
             struct InitResult
             {
                 TerminatedSkillStatus status;
             };
 
+            /// A result struct for skill preparing
             struct PrepareResult
             {
                 ActiveOrTerminatedSkillStatus status;
             };
 
+            /// A result struct for th main method of a skill
             struct MainResult
             {
                 TerminatedSkillStatus status;
                 aron::data::DictPtr data = nullptr;
             };
 
+            /// A result struct for skill exit function
             struct ExitResult
             {
                 TerminatedSkillStatus status;
             };
 
+            /// We completely remove the default constructor! A skill without a desciption cannot exist
             Skill() = delete;
+
+            /// Constructor of a skill for inheritance. Every skill must have a skill description
             Skill(const SkillDescription&);
-            virtual ~Skill() = default;
 
-            /// The id of the skill (combination of provider and name must be unique).
+            /// Virtual destructor of a skill
+            virtual ~Skill()
+            {
+                //ARMARX_IMPORTANT << "DESTROY SKILL " << getSkillId();
+            }
+
+            /// Get the id of the skill
             SkillID
             getSkillId() const
             {
                 return description.skillId;
             }
 
+            /// Get the description of a skill
             SkillDescription
             getSkillDescription() const
             {
                 return description;
             }
 
+            /// Set the provider id of the description of the skill.
+            /// This method is called when creating a skill in a skill provider
             void
             setProviderId(const skills::ProviderID& pid)
             {
                 description.skillId.providerId = pid;
             }
 
+            void
+            setCallback(const CallbackT& callback)
+            {
+                this->callback = callback;
+            }
+
+            void
+            setManager(const manager::dti::SkillManagerInterfacePrx& manager)
+            {
+                this->manager = manager;
+            }
+
+            void
+            setExecutorName(const std::string& executorName)
+            {
+                this->executorName = executorName;
+            }
+
+            /// Prepare a skill once. This method is called in a loop as long as it returns RUNNING
+            /// If the loop does not terminate with SUCCEDED the skill execution is failed.
             PrepareResult prepareSkill();
 
+            /// Initialization of a skill. Called directly after construction.
+            /// If this method does not return SUCCEEDED the skill execution is failed.
             InitResult initSkill();
 
+            /// Main method of a skill.
             MainResult mainOfSkill();
 
+            /// Exit method of a skill. It is guaranteed that exit is always called
+            /// (unless there is a segfault or similar)
             ExitResult exitSkill();
 
-            // Condition listeners
-            // used to notify the skill from extern to stop
+            /// Notify the skill from extern to stop
             void notifySkillToStop();
 
-            // returns whether the skill should terminate as soon as possible
+            /// Returns whether the skill should terminate as soon as possible
             bool shouldSkillTerminate() const;
 
-            // merge parameters to the local parameters of the skill
-            void
-            updateParameters(const aron::data::DictPtr& d)
-            {
-                std::scoped_lock l(this->parametersMutex);
-                if (this->parameters == nullptr)
-                {
-                    this->parameters = d;
-                }
-                else
-                {
-                    this->parameters->mergeAndReplaceCopy(d);
-                }
-            }
+            /// Merge parameters to the local parameters of the skill
+            void updateParameters(const aron::data::DictPtr& d);
 
-            // hard set the parameters, ignoring everything that has been set or merged before
-            void
-            setParameters(const aron::data::DictPtr& d)
-            {
-                std::scoped_lock l(this->parametersMutex);
-                this->parameters = d;
-            }
+            /// Hard set the parameters, ignoring everything that has been set or merged before
+            void setParameters(const aron::data::DictPtr& d);
 
-            // get the parameters
-            aron::data::DictPtr
-            getParameters() const
-            {
-                std::scoped_lock l(this->parametersMutex);
-                return this->parameters;
-            }
+            /// Get the parameters of a skill that have been set so far
+            aron::data::DictPtr getParameters() const;
 
         protected:
             void throwIfSkillShouldTerminate(const std::string& abortedMessage = "");
@@ -134,12 +152,17 @@ namespace armarx
             // fires if the skill reaches timeout
             void notifyTimeoutReached();
 
+        private:
             // helper methods to do all the static initialization stuff
             InitResult _init();
             PrepareResult _prepare();
             MainResult _main();
             ExitResult _exit();
 
+            void _onTimeoutReached();
+            void _onStopRequested();
+
+        protected:
             /// Override this method with the actual implementation.
             virtual InitResult init();
 
@@ -152,7 +175,7 @@ namespace armarx
             /// Override this method with the actual implementation.
             virtual ExitResult exit();
 
-        private:
+        protected:
             /// Override these methods if you want to do something special when notification comes
             virtual void onTimeoutReached();
             virtual void onStopRequested();
@@ -162,35 +185,42 @@ namespace armarx
             void installConditionWithCallback(std::function<bool()>&& f,
                                               std::function<void()>&& cb);
 
+            /// call a subskill and block until the subskill terminates.
+            /// If you call a subskill this way it will be stopped if the current skill stops.
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const skills::SkillProxy& prx, const aron::data::DictPtr& = nullptr);
+
+            /// Similar to callSubskill but non-blocking
+            skills::SkillExecutionID callSubskillAsync(const skills::SkillProxy& prx,
+                                                       const aron::data::DictPtr& = nullptr);
+
         public:
             // running params
             armarx::core::time::DateTime started = armarx::core::time::DateTime::Now();
             armarx::core::time::DateTime exited = armarx::core::time::DateTime::Invalid();
 
-            // parameterization. Will be set from implementation wrapper.
-            // const params after initialization!!
-            CallbackT callback;
+        protected:
+            // parameterization. Will be set from implementation wrapper. No getters available
+            // const after construction!!
+            CallbackT callback = CallbackT();
             manager::dti::SkillManagerInterfacePrx manager = nullptr;
-            std::string executorName = "INVALID EXECUTOR NAME";
+            std::string executorName = "";
 
         protected:
-            // non-const params
+            // non-const params. Const after preparation. Getters are available
             mutable std::mutex parametersMutex;
             armarx::aron::data::DictPtr parameters = nullptr;
 
             // The descripion of the skill
             SkillDescription description;
 
-            // active conditions. First is condition (bool return func)
-            mutable std::mutex conditionCallbacksMutex;
-            std::vector<std::pair<std::function<bool()>, std::function<void()>>>
-                conditionCallbacks = {};
-
-            // Status variables.
+            // Status variables
             std::atomic_bool constructing = true;
             std::atomic_bool initializing = false;
             std::atomic_bool preparing = false;
             std::atomic_bool running = false;
+            std::atomic_bool exiting = false;
+            std::atomic_bool finished = false;
 
             // Conditionals to indicate that an event has occured. Use conditions this way
             std::atomic_bool stopped = false;
@@ -198,8 +228,16 @@ namespace armarx
 
 
         private:
-            std::thread conditionCheckingThread; // A therad that checks the conditions frequently
+            // active conditions. First is condition (bool return func)
+            mutable std::mutex conditionCallbacksMutex;
+            std::vector<std::pair<std::function<bool()>, std::function<void()>>>
+                conditionCallbacks = {};
+
+            std::thread conditionCheckingThread; // A thread that checks the conditions frequently
             armarx::Frequency conditionCheckingThreadFrequency = armarx::Frequency::Hertz(20);
+
+            mutable std::mutex subskillsMutex;
+            std::vector<skills::SkillExecutionID> subskills;
         };
 
         template <class T>
diff --git a/source/RobotAPI/libraries/skills/core/SkillExecutionID.h b/source/RobotAPI/libraries/skills/core/SkillExecutionID.h
index f639b4b4e1f619fa7347f462395714e8b864e005..6d9975bb469eead6760e260ead049dec5e1ab4ea 100644
--- a/source/RobotAPI/libraries/skills/core/SkillExecutionID.h
+++ b/source/RobotAPI/libraries/skills/core/SkillExecutionID.h
@@ -18,10 +18,6 @@ namespace armarx
     {
         struct SkillExecutionID
         {
-            SkillID skillId;
-            std::string executorName;
-            armarx::core::time::DateTime executionStartedTime;
-
             SkillExecutionID() = default;
             SkillExecutionID(const SkillID&,
                              const std::string& executorName,
@@ -30,26 +26,26 @@ namespace armarx
             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;
+                return this->toString() == other.toString();
             }
 
             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;
+                return this->toString() < other.toString();
+            }
+
+            bool
+            operator<=(const SkillExecutionID& other) const
+            {
+                return this->toString() <= other.toString();
+            }
+
+            std::string
+            toString() const
+            {
+                return skillId.toString() + " requested by " + executorName + " at " +
+                       executionStartedTime.toDateTimeString();
             }
 
             skills::manager::dto::SkillExecutionID toManagerIce() const;
@@ -60,6 +56,11 @@ namespace armarx
 
             static SkillExecutionID FromIce(const skills::provider::dto::SkillExecutionID&,
                                             const std::optional<skills::ProviderID>& providerName);
+
+
+            SkillID skillId;
+            std::string executorName;
+            armarx::core::time::DateTime executionStartedTime;
         };
 
     } // namespace skills
diff --git a/source/RobotAPI/libraries/skills/core/SkillProxy.cpp b/source/RobotAPI/libraries/skills/core/SkillProxy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f73c43dfd152c756f80e5ac3e83e901fe59e8ee1
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/core/SkillProxy.cpp
@@ -0,0 +1,118 @@
+#include "SkillProxy.h"
+
+#include <chrono>
+#include <thread>
+
+namespace armarx
+{
+    namespace skills
+    {
+        SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
+                               const SkillID& skillId) :
+            manager(manager)
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            skillDescription = SkillDescription::FromIce(
+                manager->getSkillDescription(skillId.toManagerIce()).value());
+            ARMARX_CHECK(skillDescription.skillId.isFullySpecified());
+        }
+
+        SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
+                               const SkillDescription& skillDesc) :
+            manager(manager), skillDescription(skillDesc)
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            ARMARX_CHECK(skillDesc.skillId.isFullySpecified());
+        }
+
+        SkillDescription
+        SkillProxy::getSkillDescription() const
+        {
+            return skillDescription;
+        }
+
+        SkillID
+        SkillProxy::getSkillId() const
+        {
+            return skillDescription.skillId;
+        }
+
+        TerminatedSkillStatusUpdate
+        SkillProxy::executeSkill(const std::string& executorName,
+                                 const aron::data::DictPtr& params) const
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            skills::manager::dto::SkillExecutionRequest req;
+            req.executorName = executorName;
+            req.parameters = aron::data::Dict::ToAronDictDTO(params);
+            req.skillId = skillDescription.skillId.toManagerIce();
+
+            auto terminatingUpdateIce = manager->executeSkill(req);
+            return TerminatedSkillStatusUpdate::FromIce(terminatingUpdateIce);
+        }
+
+        SkillExecutionID
+        SkillProxy::executeSkillAsync(const std::string& executorName,
+                                      const aron::data::DictPtr& params) const
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            skills::manager::dto::SkillExecutionRequest req;
+            req.executorName = executorName;
+            req.parameters = aron::data::Dict::ToAronDictDTO(params);
+            req.skillId = skillDescription.skillId.toManagerIce();
+
+            auto execIdIce = manager->executeSkillAsync(req);
+            return SkillExecutionID::FromIce(execIdIce);
+        }
+
+        std::optional<TerminatedSkillStatusUpdate>
+        SkillProxy::join(const SkillExecutionID& executionId) const
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            auto s = this->manager->getSkillExecutionStatus(executionId.toManagerIce());
+
+            while (s)
+            {
+                auto statusUpdate = skills::SkillStatusUpdate::FromIce(*s);
+
+                if (statusUpdate.hasBeenTerminated())
+                {
+                    break;
+                }
+
+                std::this_thread::sleep_for(std::chrono::milliseconds(50));
+                s = this->manager->getSkillExecutionStatus(executionId.toManagerIce());
+            }
+
+            if (!s)
+            {
+                // Either the manager already removed the result (then it is unknown) or the execution id does not exist.
+                return std::nullopt;
+            }
+
+            return TerminatedSkillStatusUpdate::FromIce(*s);
+        }
+
+        bool
+        SkillProxy::abortSkill(const SkillExecutionID& id) const
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            auto r = manager->abortSkill(id.toManagerIce());
+            return r.success;
+        }
+
+        bool
+        SkillProxy::abortSkillAsync(const SkillExecutionID& id) const
+        {
+            ARMARX_CHECK_NOT_NULL(manager);
+            auto r = manager->abortSkillAsync(id.toManagerIce());
+            return r.success;
+        }
+
+        aron::data::DictPtr
+        SkillProxy::getRootProfileParameters() const
+        {
+            return skillDescription.rootProfileDefaults;
+        }
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/core/SkillProxy.h b/source/RobotAPI/libraries/skills/core/SkillProxy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e20ca01a0bc4b6de877e34a3ad6bc0edcbaa4689
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/core/SkillProxy.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <RobotAPI/libraries/skills/core/SkillDescription.h>
+#include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h>
+
+namespace armarx
+{
+    namespace skills
+    {
+        /* Manages the remote execution of a skill and converts the ice types */
+        class SkillProxy : public armarx::Logging
+        {
+        public:
+            /// We remove the default constructor as every skill proxy requires a manager
+            SkillProxy() = delete;
+
+            /// set the skill proxy using a skillId. Queries the manager to get the description.
+            SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
+                       const SkillID& skillId);
+
+            /// set the proxy using a skill description
+            SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
+                       const SkillDescription& skillDesc);
+
+            /// copy ctor
+            SkillProxy(const SkillProxy& o) = default;
+
+            /// get the skill description
+            SkillDescription getSkillDescription() const;
+
+            /// get the skill id from the skill description
+            SkillID getSkillId() const;
+
+            // Provide a similar API as the skillprovider
+            /// execute a skill and block until skill terminates
+            TerminatedSkillStatusUpdate
+            executeSkill(const std::string& executorName,
+                         const aron::data::DictPtr& params = nullptr) const;
+
+            /// execute a skill. Do not block during execution
+            SkillExecutionID executeSkillAsync(const std::string& executorName,
+                                               const aron::data::DictPtr& params = nullptr) const;
+
+            /// poll execution status and block until its null or terminated
+            std::optional<TerminatedSkillStatusUpdate>
+            join(const SkillExecutionID& executionId) const;
+
+            /// ask skill to abort ASAP. Blocks until skill stopped
+            bool abortSkill(const SkillExecutionID& executionId) const;
+
+            /// ask skill to abort ASAP
+            bool abortSkillAsync(const SkillExecutionID& executionId) const;
+
+            // Utiliy methods
+            /// get the default parameters of the skill. TODO: Skill profiles in memory!
+            aron::data::DictPtr getRootProfileParameters() const;
+
+        protected:
+            manager::dti::SkillManagerInterfacePrx manager;
+            SkillDescription skillDescription;
+        };
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
index 4b7cdec1b588ee65f80d188ccd786623b5e9665c..233aa841b730c6f096393634d417bd41eccd7e93 100644
--- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp
@@ -580,9 +580,6 @@ namespace armarx
         this->plugin->removeProvider(i);
     }
 
-    using SkillProviderInterfacePrxMap =
-        std::map<std::string, skills::provider::dti::SkillProviderInterfacePrx>;
-
     skills::manager::dto::SkillStatusUpdate
     SkillManagerComponentPluginUser::executeSkill(
         const skills::manager::dto::SkillExecutionRequest& info,
diff --git a/source/RobotAPI/libraries/skills/provider/CMakeLists.txt b/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
index 5ccff912099114655eb96dd46c9e61966f677df7..fba16f3e70fe8849748369529001df24644ffc87 100644
--- a/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
@@ -21,7 +21,6 @@ armarx_add_library(
         LambdaSkill.cpp
         SimpleSkill.cpp
         SimpleSpecializedSkill.cpp
-        SkillProxy.cpp
         SpecializedSkillProxy.cpp
         PeriodicSkill.cpp
         SpecializedSkill.cpp
@@ -36,7 +35,6 @@ armarx_add_library(
         LambdaSkill.h
         SimpleSkill.h
         SimpleSpecializedSkill.h
-        SkillProxy.h
         SpecializedSkillProxy.h
         PeriodicSkill.h
         SpecializedSkill.h
diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp
index 02ad14bc1e789ad62c9d13d9ece923f35fac7e15..197159cb79a4401ade9895b14936fc65a8bf3996 100644
--- a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp
@@ -47,8 +47,10 @@ namespace armarx::skills
     {
         armarx::core::time::Metronome metronome(frequency);
 
-        while (not Skill::shouldSkillTerminate())
+        while (true)
         {
+            this->throwIfSkillShouldTerminate();
+
             const auto res = stepOfSkill();
             switch (res.status)
             {
@@ -56,11 +58,11 @@ namespace armarx::skills
                     // nothing to do here
                     break;
                 case ActiveOrTerminatedSkillStatus::Aborted:
-                    return {TerminatedSkillStatus::Aborted, res.data};
+                    return MakeAbortedResult();
                 case ActiveOrTerminatedSkillStatus::Succeeded:
-                    return {TerminatedSkillStatus::Succeeded, res.data};
+                    return MakeSucceededResult(res.data);
                 case ActiveOrTerminatedSkillStatus::Failed:
-                    return {TerminatedSkillStatus::Failed, res.data};
+                    return MakeFailedResult();
             }
 
             const auto sleepDuration = metronome.waitForNextTick();
@@ -72,18 +74,8 @@ namespace armarx::skills
             }
         }
 
-        if (stopped)
-        {
-            return {TerminatedSkillStatus::Aborted, nullptr};
-        }
-
-        if (timeoutReached)
-        {
-            ARMARX_WARNING << "The skill " << getSkillId().toString() << " reached timeout!";
-            return {TerminatedSkillStatus::Failed, nullptr};
-        }
-
-        throw skills::error::SkillException(__PRETTY_FUNCTION__, "Should not happen!");
+        // never happens
+        return MakeSucceededResult();
     }
 
     PeriodicSkill::StepResult
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
index 1a5b0b0d19877cd00da786cc82fed4df690efecc..e5c169c04ff1ea7dc1ed5cf7ed59f136f1406b9c 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
@@ -120,7 +120,7 @@ namespace armarx::plugins
         ARMARX_CHECK(execId.skillId.isSkillSpecified());
 
         const std::unique_lock l(skillExecutionsMutex);
-        if (skillExecutions.find(execId) != skillExecutions.end())
+        if (skillExecutions.find(execId) == skillExecutions.end())
         {
             ARMARX_WARNING << "Skill execution for skill '" + execId.skillId.toString() +
                                   "' not found!";
@@ -276,6 +276,21 @@ namespace armarx::plugins
                 });
         }
 
+        // wait until skill is constructed. This assures, that a status update exists.
+        while (true)
+        {
+            {
+                std::scoped_lock l(wrapper->skillStatusesMutex);
+
+                if (wrapper->statusUpdate.hasBeenConstructed())
+                {
+                    break;
+                }
+            }
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(20));
+        }
+
         return executionId;
     }
 
@@ -320,11 +335,21 @@ namespace armarx::plugins
             return false;
         }
 
-        it->second.stopSkill();
+        auto& runtime = it->second;
+        runtime.stopSkill();
 
-        if (auto it = skillExecutions.find(executionId); it != skillExecutions.end())
+        while (true)
         {
-            skillExecutions.erase(it);
+            {
+                std::scoped_lock l(runtime.skillStatusesMutex);
+                auto status = runtime.statusUpdate;
+
+                if (status.hasBeenTerminated())
+                {
+                    break;
+                }
+            }
+            std::this_thread::sleep_for(std::chrono::milliseconds(20));
         }
 
         return true;
@@ -344,7 +369,7 @@ namespace armarx::plugins
             return false;
         }
 
-        std::thread([&]() { it->second.stopSkill(); });
+        it->second.stopSkill();
         return true;
     }
 
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp b/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp
deleted file mode 100644
index 50758fde754abe7434b677c53c54ff28a321430c..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "SkillProxy.h"
-
-namespace armarx
-{
-    namespace skills
-    {
-        SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
-                               const SkillID& skillId) :
-            manager(manager),
-            skillDescription(SkillDescription::FromIce(
-                manager->getSkillDescription(skillId.toManagerIce()).value()))
-        {
-        }
-
-        SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
-                               const SkillDescription& skillDesc) :
-            manager(manager), skillDescription(skillDesc)
-        {
-            ARMARX_CHECK(skillDesc.skillId.isFullySpecified());
-        }
-
-        TerminatedSkillStatusUpdate
-        SkillProxy::executeSkill(const std::string& executorName, const aron::data::DictPtr& params)
-        {
-            skills::manager::dto::SkillExecutionRequest req;
-            req.executorName = executorName;
-            req.parameters = params->toAronDictDTO();
-            req.skillId = skillDescription.skillId.toManagerIce();
-
-            auto terminatingUpdateIce = manager->executeSkill(req);
-            return TerminatedSkillStatusUpdate::FromIce(terminatingUpdateIce);
-        }
-
-        SkillExecutionID
-        SkillProxy::executeSkillAsync(const std::string& executorName,
-                                      const aron::data::DictPtr& params)
-        {
-            skills::manager::dto::SkillExecutionRequest req;
-            req.executorName = executorName;
-            req.parameters = params->toAronDictDTO();
-            req.skillId = skillDescription.skillId.toManagerIce();
-
-            auto execReqIce = manager->executeSkillAsync(req);
-            return SkillExecutionID::FromIce(execReqIce);
-        }
-
-        bool
-        SkillProxy::abortSkill(const SkillExecutionID& id)
-        {
-            auto r = manager->abortSkill(id.toManagerIce());
-            return r.success;
-        }
-
-        bool
-        SkillProxy::abortSkillAsync(const SkillExecutionID& id)
-        {
-            auto r = manager->abortSkillAsync(id.toManagerIce());
-            return r.success;
-        }
-
-        aron::data::DictPtr
-        SkillProxy::getDefaultParameters(const std::string& profileName)
-        {
-            if (profileName == "root")
-            {
-                return skillDescription.rootProfileDefaults;
-            }
-            // TODO @fabianPK
-            return nullptr;
-        }
-    } // namespace skills
-} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProxy.h b/source/RobotAPI/libraries/skills/provider/SkillProxy.h
deleted file mode 100644
index 8f0fb34be58e7d20fec5778795ead2a34ab80a3c..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/skills/provider/SkillProxy.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#include <RobotAPI/libraries/skills/core/Skill.h>
-
-namespace armarx
-{
-    namespace skills
-    {
-        /* Manages the remote execution of a skill and converts the ice types */
-        class SkillProxy : public armarx::Logging
-        {
-        public:
-            SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
-                       const SkillID& skillId);
-            SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
-                       const SkillDescription& skillDesc);
-
-            // Provide a similar API as the skillprovider
-            TerminatedSkillStatusUpdate executeSkill(const std::string& executorName,
-                                                     const aron::data::DictPtr& params = nullptr);
-
-            SkillExecutionID executeSkillAsync(const std::string& executorName,
-                                               const aron::data::DictPtr& params = nullptr);
-
-            bool abortSkill(const SkillExecutionID& executorName);
-
-            bool abortSkillAsync(const SkillExecutionID& executorName);
-
-            // Utiliy methods
-            aron::data::DictPtr getDefaultParameters(const std::string& profileName = "root");
-
-        protected:
-            manager::dti::SkillManagerInterfacePrx manager;
-            SkillDescription skillDescription;
-        };
-    } // namespace skills
-} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.cpp b/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.cpp
index 1074f549947ce61b4b96e3f698caab84a5149488..4f372c5f55247795f91d956f92d84eb6ac35ee77 100644
--- a/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.cpp
@@ -1,4 +1,4 @@
-#include "SkillProxy.h"
+#include "SpecializedSkillProxy.h"
 
 namespace armarx
 {
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.h
index 37ecd5a7771f09f99d11c0513cdcf95fe7c5d8e0..4dd53171c4cf17c7298cf9ba59c364ddcf81eb8e 100644
--- a/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.h
+++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkillProxy.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include "SkillProxy.h"
+#include <RobotAPI/libraries/skills/core/SkillProxy.h>
 
 namespace armarx
 {
@@ -27,9 +27,9 @@ namespace armarx
 
             // Utiliy methods
             AronT
-            getDefaultParameters(const std::string& profileName = "root")
+            getRootProfileParameters()
             {
-                auto dict = SkillProxy::getDefaultParameters(profileName);
+                auto dict = SkillProxy::getRootProfileParameters();
                 if (dict)
                 {
                     return AronT::FromAron(dict);
diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
index 4ac4757e2323a2d26adc6921e293b9062e0b449c..5c20567a2592e8e53c547e8dad8073fe50e779b5 100644
--- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
+++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
@@ -65,6 +65,8 @@ namespace armarx
             const auto& skillName = skillId.skillName;
             const auto& providerId = *skillId.providerId;
             const auto& executorName = statusUpdate.executionId.executorName;
+            const auto& manager =
+                skills::manager::dti::SkillManagerInterfacePrx::checkedCast(callback_interface);
 
             ARMARX_INFO_S << "Executing skill: " << skillName;
 
@@ -119,12 +121,10 @@ namespace armarx
 
             updateStatus(SkillStatus::Constructing);
             this->skill = this->factory.createSkill(providerId);
-            this->skill->executorName = executorName;
-            this->skill->manager = skills::manager::dti::SkillManagerInterfacePrx::checkedCast(
-                callback_interface); // ugly. Get managerPrx from manager!
-
-            this->skill->callback = [&](const SkillStatus s, const armarx::aron::data::DictPtr& d)
-            { updateStatus(s, d); };
+            this->skill->setExecutorName(executorName);
+            this->skill->setManager(manager);
+            this->skill->setCallback([&](const SkillStatus s, const armarx::aron::data::DictPtr& d)
+                                     { updateStatus(s, d); });
 
             // set initial parameters that were attached to the execution request (only add as we are not sure whether some updates already arrived)
             skill->updateParameters(initial_aron_params);