diff --git a/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg b/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg
index 340a7f1e6fafa4118860e3d6a8ace505b9b9bf1d..bbfc7a0ca3a8eddd35f8c447efb327bbbe260c48 100644
--- a/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg
+++ b/scenarios/ArMemObjectMemory/config/ArticulatedObjectExampleMemoryWriterClient.cfg
@@ -44,35 +44,35 @@
 # ArmarX.ArticulatedObjectExampleMemoryWriterClient.ObjectName = ""
 
 
-# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem:  Ice object name of the `MemoryNameSystem` component.
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ArMemMemoryNameSystem:  Ice object name of the `MemoryNameSystem` component.
 #  Attributes:
 #  - Default:            ArMemMemoryNameSystem
 #  - Case sensitivity:   yes
 #  - Required:           no
-ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem = MemoryNameSystem
+ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ArMemMemoryNameSystem = MemoryNameSystem
 
 
-# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.CoreSegment:  Name of the memory core segment to use.
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.CoreSegment:  Name of the memory core segment to use for object classes.
 #  Attributes:
-#  - Default:            ArticulatedObjectInstance
+#  - Default:            ArticulatedObjectClass
 #  - Case sensitivity:   yes
 #  - Required:           no
-# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.CoreSegment = ArticulatedObjectInstance
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.CoreSegment = ArticulatedObjectClass
 
 
-# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName:  
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.MemoryName:  
 #  Attributes:
-#  - Default:            ObjectMemory
+#  - Default:            Object
 #  - Case sensitivity:   yes
 #  - Required:           no
-ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName = Object
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.MemoryName = Object
 
 
-# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName:  
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ProviderName:  
 #  Attributes:
 #  - Case sensitivity:   yes
 #  - Required:           yes
-ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName = ExampleProvider
+ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.ProviderName = ExampleProvider
 
 
 # ArmarX.ArticulatedObjectExampleMemoryWriterClient.tpc.pub.DebugObserver:  Name of the `DebugObserver` topic to publish data to.
@@ -225,3 +225,18 @@ ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.Prov
 # ArmarX.Verbosity = Info
 
 
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem:  
+#  Attributes:
+ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ArMemMemoryNameSystem = MemoryNameSystem
+
+
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName:  
+#  Attributes:
+ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.MemoryName = Object
+
+
+# ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName:  
+#  Attributes:
+ArmarX.ArticulatedObjectExampleMemoryWriterClient.mem.obj.articulated.write.ProviderName = ExampleProvider
+
+
diff --git a/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp b/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp
index 553a24c85e79c7353c09893df04212e17c2c1fb8..4d45a76b229a11ac6570fb519ff3b2eb0cadd048 100644
--- a/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp
+++ b/source/RobotAPI/components/armem/client/ArticulatedObjectExampleMemoryWriterClient/ArticulatedObjectExampleMemoryWriterClient.cpp
@@ -69,7 +69,6 @@ namespace armarx::articulated_object
     {
         const std::string xml =
             "./ArmarXObjects/Environment/mobile-kitchen/dishwasher-only/dishwasher.xml";
-        const std::string name = "dishwasher";
 
         return VirtualRobot::RobotIO::loadRobot(ArmarXDataPath::resolvePath(xml), VirtualRobot::RobotIO::eStructure);
     }
@@ -85,6 +84,7 @@ namespace armarx::articulated_object
                 .name = obj.getName(),
                 .xml = PackagePath(armarx::ArmarXDataPath::getProject({"ArmarXObjects"}, obj.getFilename()), obj.getFilename())
             },
+            .instance = "", // TODO(fabian.reister):
             .config = {
                 .timestamp = timestamp,
                 .globalPose = Eigen::Affine3f(obj.getRootNode()->getGlobalPose()),
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
index ed69e4c80c5bc975c1acd46ffb7b57e4418915d7..e1f73815a610f18139205f8a1a0c776a3ef797f7 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
@@ -21,6 +21,7 @@ namespace armarx::armem::articulated_object
         ArticulatedObject obj
         {
             .description = description,
+            .instance = "", // TODO(fabian.reister):
             .config = {}, // will be populated by synchronize
             .timestamp = timestamp
         };
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
index 3fe33b6c6bc69f61a4721a014cb2618a5f59d905..170afc2113293244c8dcc90245227db8f3744549 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
@@ -30,12 +30,12 @@ namespace armarx::armem::articulated_object
 
         struct Properties
         {
-            std::string memoryName       = "ObjectMemory";
+            std::string memoryName       = "Object";
             std::string coreSegmentName  = "ArticulatedObjectInstance";
             std::string providerName;
         } properties;
 
-        const std::string propertyPrefix = "mem.obj.articulated.read.";
+        const std::string propertyPrefix = "mem.obj.articulated.";
 
         armem::client::Reader memoryReader;
         std::mutex memoryWriterMutex;
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
index ea8545699d4dbc85a3a135ca3efb269d2a0f755c..cffcbdbb32fb0ad70d983174596de9fa799ccd5c 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
@@ -1,9 +1,13 @@
 #include "Writer.h"
 
+#include "ArmarXCore/core/logging/Logging.h"
+#include "RobotAPI/libraries/armem/core/MemoryID.h"
 #include "RobotAPI/libraries/armem_objects/aron_conversions.h"
 
+#include <RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h>
 #include <mutex>
 #include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
+#include <optional>
 
 
 namespace armarx::armem::articulated_object
@@ -18,12 +22,14 @@ namespace armarx::armem::articulated_object
 
         const std::string prefix = getPropertyPrefix();
 
-        def->optional(properties.coreSegmentName,
-                      prefix + "CoreSegment",
-                      "Name of the memory core segment to use.");
-
         def->optional(properties.memoryName, prefix + "MemoryName");
 
+        def->optional(properties.coreInstanceSegmentName,
+                      prefix + "CoreSegment",
+                      "Name of the memory core segment to use for object instances.");
+        def->optional(properties.coreClassSegmentName,
+                      prefix + "CoreSegment",
+                      "Name of the memory core segment to use for object classes.");
         def->required(properties.providerName, prefix + "ProviderName");
     }
 
@@ -41,16 +47,111 @@ namespace armarx::armem::articulated_object
         ARMARX_IMPORTANT << "Writer: Connected to memory '" << properties.memoryName;
 
         memoryWriter.setWritingMemory(result.proxy);
+        memoryReader.setReadingMemory(result.proxy);
+
+        const auto resultCoreClassSegment = memoryWriter.addSegment(properties.coreClassSegmentName, properties.providerName);
+
+        const auto resultCoreInstanceSegmentName =
+            memoryWriter.addSegment(properties.coreInstanceSegmentName, properties.providerName);
+
+        armem::MemoryID refId = armem::MemoryID(resultCoreClassSegment.segmentID);
+
+        armem::MemoryID id;
+        id.setCoreSegmentID(refId); // listen to all provider segments!
+
+        memoryReader.subscribe(id, this, &Writer::updateKnownObjects);
     }
 
-    bool Writer::store(const ArticulatedObject& obj)
+    void Writer::updateKnownObject(const armem::MemoryID& snapshotId)
+    {
+
+        arondto::RobotDescription aronArticulatedObjectDescription;
+        // aronArticulatedObjectDescription.fromAron(snapshotId.ent);
+
+        // TODO(fabian.reister): implement
+    }
+
+    void Writer::updateKnownObjects(const armem::MemoryID& subscriptionID, const std::vector<armem::MemoryID>& snapshotIDs)
+    {
+        ARMARX_INFO << "New objects available!";
+
+        std::for_each(snapshotIDs.begin(), snapshotIDs.end(), [&](const auto & snapshotID)
+        {
+            updateKnownObject(snapshotID);
+        });
+    }
+
+    std::optional<armem::MemoryID> Writer::storeOrGetClass(const ArticulatedObject& obj)
+    {
+        const auto objectId = knownObjects.find(obj.description.name);
+
+        // check if exists
+        if (objectId != knownObjects.end())
+        {
+            return objectId->second;
+        }
+
+        // otherwise create
+        return storeClass(obj);
+    }
+
+    std::optional<armem::MemoryID> Writer::storeClass(const ArticulatedObject& obj)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        ARMARX_DEBUG << "Trying to create core segment + provider segment";
+
+        // TODO(fabian.reister): variable provider segment
+        const auto result = memoryWriter.addSegment(properties.coreClassSegmentName, properties.providerName);
+
+        if (not result.success)
+        {
+            ARMARX_ERROR << "Creating core segment failed. Reason: " << result.errorMessage;
+            return std::nullopt;
+        }
+
+        const auto& timestamp = obj.timestamp;
+
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId
+            .withEntityName(obj.description.name)
+            .withTimestamp(timestamp);
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+
+        arondto::RobotDescription aronArticulatedObjectDescription;
+        toAron(aronArticulatedObjectDescription, obj.description);
+
+        update.instancesData = {aronArticulatedObjectDescription.toAron()};
+        update.timeCreated   = timestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+            return std::nullopt;
+        }
+
+        // update cache (TODO: likely remove this)
+        knownObjects[obj.description.name] = updateResult.snapshotID;
+
+        return updateResult.snapshotID;
+    }
+
+    bool Writer::storeInstance(const ArticulatedObject& obj)
     {
         std::lock_guard g{memoryWriterMutex};
 
         ARMARX_DEBUG << "Trying to create core segment + provider segment";
 
         const auto result =
-            memoryWriter.addSegment(properties.coreSegmentName, properties.providerName);
+            memoryWriter.addSegment(properties.coreInstanceSegmentName, properties.providerName);
 
         if (not result.success)
         {
@@ -88,6 +189,20 @@ namespace armarx::armem::articulated_object
         return updateResult.success;
     }
 
+    bool Writer::store(const ArticulatedObject& obj)
+    {
+        const std::optional<armem::MemoryID> classId = storeOrGetClass(obj);
+
+        if (not classId)
+        {
+            ARMARX_WARNING << "Could not get class id!";
+            return false;
+        }
+
+        // TODO(fabian.reister): integrate memory link
+        return storeInstance(obj);
+    }
+
     const std::string& Writer::getPropertyPrefix() const
     {
         return propertyPrefix;
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h
index e396b1c4c9090e2cf2223d219b2be0fac0a26d3d..74ec9a1de548eba30b470271080c0721eb43fb7d 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.h
@@ -3,6 +3,7 @@
 #include <mutex>
 
 #include "RobotAPI/libraries/armem/client/MemoryConnector.h"
+#include "RobotAPI/libraries/armem/client/Reader.h"
 #include "RobotAPI/libraries/armem/client/Writer.h"
 
 #include "interfaces.h"
@@ -19,28 +20,42 @@ namespace armarx::armem::articulated_object
         Writer(ManagedIceObject& component);
         virtual ~Writer() = default;
 
-        bool store(const ArticulatedObject& obj) override;
-
 
         void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
         void connect();
 
+
+        bool store(const ArticulatedObject& obj) override;
+
+        bool storeInstance(const ArticulatedObject& obj);
+        std::optional<armem::MemoryID> storeClass(const ArticulatedObject& obj);
+
         const std::string& getPropertyPrefix() const override;
 
     private:
+        std::optional<armem::MemoryID> storeOrGetClass(const ArticulatedObject& obj);
+
+        void updateKnownObjects(const armem::MemoryID& subscriptionID, const std::vector<armem::MemoryID>& snapshotIDs);
+        void updateKnownObject(const armem::MemoryID& snapshotId);
 
         struct Properties
         {
-            std::string memoryName       = "ObjectMemory";
-            std::string coreSegmentName  = "ArticulatedObjectInstance";
+            std::string memoryName              = "Object";
+            std::string coreInstanceSegmentName = "ArticulatedObjectInstance";
+            std::string coreClassSegmentName    = "ArticulatedObjectClass";
             std::string providerName;
         } properties;
 
-        const std::string propertyPrefix = "mem.obj.articulated.write.";
+        const std::string propertyPrefix = "mem.obj.articulated.";
 
         armem::client::Writer memoryWriter;
         std::mutex memoryWriterMutex;
 
+        armem::client::Reader memoryReader;
+        std::mutex memoryReaderMutex;
+
+        // key: name of object: RobotDescription::name
+        std::map<std::string, MemoryID> knownObjects;
     };
 
 
diff --git a/source/RobotAPI/libraries/armem_objects/types.h b/source/RobotAPI/libraries/armem_objects/types.h
index 0db042762ef9e95da2508be38da71688a722a49f..a127850fe89fde6a635e360aba51e4a13f7d95b7 100644
--- a/source/RobotAPI/libraries/armem_objects/types.h
+++ b/source/RobotAPI/libraries/armem_objects/types.h
@@ -20,6 +20,7 @@ namespace armarx::armem
 
         std::string name;
         PackagePath xml;
+
     };
 
 
@@ -34,6 +35,8 @@ namespace armarx::armem
     struct Robot
     {
         RobotDescription description;
+        std::string instance;
+
         RobotState config;
 
         IceUtil::Time timestamp;