diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index 8e65efbcd2c10e3c68d4f6c23aade3293c8318e9..2b4b5344c2321ab58bc3fb6749dc6b2810405ecd 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -30,7 +30,9 @@ set(LIB_FILES
     memory/InternalCommit.cpp
     memory/Memory.cpp
     memory/ProviderSegment.cpp
+
     memory/detail/EntityStorage.cpp
+    memory/detail/MemoryLevel.cpp
 
     mns/MemoryNameSystem.cpp
     mns/MemoryNameSystemClientPlugin.cpp
@@ -69,8 +71,10 @@ set(LIB_HEADERS
     memory/InternalCommit.h
     memory/Memory.h
     memory/ProviderSegment.h
+
     memory/detail/EntityStorage.h
     memory/detail/MemoryContainer.h
+    memory/detail/MemoryLevel.h
 
     mns/MemoryNameSystem.h
     mns/MemoryNameSystemClientPlugin.h
diff --git a/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
index f2590c4adb6bd6b3c021be6dd084c32f7e89e182..c5bbf7554d71b152e1e70e0ca9c984ba6794d69f 100644
--- a/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/memory/CoreSegment.cpp
@@ -57,13 +57,13 @@ namespace armarx::armem
         }
         else
         {
-            throw armem::error::MissingEntry("provider segment", name, "core segment", this->name);
+            throw armem::error::MissingEntry("provider segment", name, getLevelName(), this->name);
         }
     }
 
     const Entity& CoreSegment::getEntity(const MemoryID& id) const
     {
-        checkStorageName(id.coreSegmentName, this->name, "core segment");
+        checkStorageName(id.coreSegmentName, this->name, getLevelName());
         return getProviderSegment(id.providerSegmentName).getEntity(id);
     }
 
@@ -83,7 +83,7 @@ namespace armarx::armem
     {
         if (hasProviderSegment(name))
         {
-            throw armem::error::StorageEntryAlreadyExists("provider segment", name, "core segment", this->name);
+            throw armem::error::StorageEntryAlreadyExists("provider segment", name, getLevelName(), this->name);
         }
         auto it = providerSegments.emplace(providerSegment->name, std::move(providerSegment)).first;
         ARMARX_CHECK_NOT_NULL(it->second);
@@ -93,7 +93,7 @@ namespace armarx::armem
 
     MemoryID CoreSegment::update(const InternalEntityUpdate& update)
     {
-        checkStorageName(update.entityID.coreSegmentName, this->name, "core segment");
+        checkStorageName(update.entityID.coreSegmentName, this->name, getLevelName());
 
         auto it = this->providerSegments.find(update.entityID.providerSegmentName);
         if (it != providerSegments.end())
@@ -103,13 +103,8 @@ namespace armarx::armem
         else
         {
             throw armem::error::MissingEntry("provider segment", update.entityID.providerSegmentName,
-                                             "core segment", name);
+                                             getLevelName(), name);
         }
     }
 
-    void CoreSegment::clear()
-    {
-        providerSegments.clear();
-    }
-
 }
diff --git a/source/RobotAPI/libraries/armem/memory/CoreSegment.h b/source/RobotAPI/libraries/armem/memory/CoreSegment.h
index 6a9e30da50158a93bdaf6ee30d52f18f5321b12b..aeccaabb3d96c992d12ffa23eeffa832fbe9a228 100644
--- a/source/RobotAPI/libraries/armem/memory/CoreSegment.h
+++ b/source/RobotAPI/libraries/armem/memory/CoreSegment.h
@@ -56,9 +56,6 @@ namespace armarx::armem
         /// Move and insert a provider segment.
         ProviderSegment& addProviderSegment(ProviderSegmentPtr&& providerSegment);
 
-        /// Clear the provider segments.
-        void clear() override;
-
         /// Get an cleared copy of `*this` (without provider segments).
         CoreSegmentPtr getEmptyCopy() const;
 
@@ -69,12 +66,14 @@ namespace armarx::armem
         std::map<std::string, ProviderSegmentPtr> providerSegments;
 
 
-        // MemoryContainer interface
+        // MemoryLevel interface
     public:
         std::string getLevelName() const override
         {
             return "core segment";
         }
+
+        // MemoryContainer interface
     protected:
         ContainerT& _underlyingContainer() override
         {
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.cpp b/source/RobotAPI/libraries/armem/memory/Entity.cpp
index 712f48380262c82b7bef372417843c21adb007a4..8387424e7f5f27e396106f117977d2bf1b8ab5c6 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/memory/Entity.cpp
@@ -66,7 +66,7 @@ namespace armarx::armem
         else
         {
             throw error::MissingEntry("entity snapshot", toDateTimeMilliSeconds(time),
-                                      "entity", this->name);
+                                      getLevelName(), this->name);
         }
     }
 
@@ -169,7 +169,7 @@ namespace armarx::armem
     {
         if (name != this->name)
         {
-            throw armem::error::StorageNameMismatch(name, "entity", this->name);
+            throw armem::error::StorageNameMismatch(name, getLevelName(), this->name);
         }
     }
 
@@ -182,14 +182,4 @@ namespace armarx::armem
         return *history.rbegin();
     }
 
-    std::string Entity::getLevelName() const
-    {
-        return "entity";
-    }
-
-    Entity::ContainerT& Entity::_underlyingContainer()
-    {
-        return history;
-    }
-
 }
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.h b/source/RobotAPI/libraries/armem/memory/Entity.h
index 46edfeffcecd6ba5ceda5b3389e216b90643fb12..5477509b17618509b24cc8efe7269ae69e3c4408 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.h
+++ b/source/RobotAPI/libraries/armem/memory/Entity.h
@@ -19,7 +19,9 @@ namespace armarx::armem
     /**
      * @brief Data of an entity over a period of time.
      */
-    class Entity : public detail::MemoryContainer<std::map<Time, EntitySnapshotPtr>>
+    class Entity :
+        public detail::MemoryLevel,
+        public detail::MemoryContainer<std::map<Time, EntitySnapshotPtr>>
     {
     public:
 
@@ -116,11 +118,23 @@ namespace armarx::armem
 
 
 
-        // MemoryContainer interface
+        // MemoryLevel interface
     public:
-        std::string getLevelName() const override;
+        std::string getKeyString() const override
+        {
+            return name;
+        }
+        std::string getLevelName() const override
+        {
+            return "entity";
+        }
+
+        // MemoryContainer interface
     protected:
-        ContainerT& _underlyingContainer() override;
+        ContainerT& _underlyingContainer() override
+        {
+            return history;
+        }
 
     };
 
diff --git a/source/RobotAPI/libraries/armem/memory/EntityData.h b/source/RobotAPI/libraries/armem/memory/EntityData.h
index 66464130886214216b19fd18b14420678acef8bc..b01196f2dfd63b9564b67bcdbac7f303f84e2d0c 100644
--- a/source/RobotAPI/libraries/armem/memory/EntityData.h
+++ b/source/RobotAPI/libraries/armem/memory/EntityData.h
@@ -8,6 +8,7 @@
 #include "../core/Time.h"
 
 #include "InternalCommit.h"
+#include "detail/MemoryLevel.h"
 
 
 namespace armarx::armem
@@ -33,7 +34,7 @@ namespace armarx::armem
     /**
      * @brief Data of a single entity instance.
      */
-    struct EntityData
+    struct EntityData : public detail::MemoryLevel
     {
         int index;
 
@@ -51,6 +52,18 @@ namespace armarx::armem
          */
         void update(const InternalEntityUpdate& update, int index);
 
+
+        // MemoryLevel interface
+    public:
+        std::string getKeyString() const override
+        {
+            return std::to_string(index);
+        }
+        std::string getLevelName() const override
+        {
+            return "entity data";
+        }
+
     };
 
     using EntityDataPtr = std::unique_ptr<EntityData>;
diff --git a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
index 8b8882b4b03920ba90f49ab7d6aa232f2ffa2cea..abe7180ad9f75f81352fc9e40815207f7baa523c 100644
--- a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
+++ b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.cpp
@@ -54,7 +54,7 @@ namespace armarx::armem
         else
         {
             throw armem::error::MissingEntry("instance", std::to_string(index),
-                                             "entity snapshot", toDateTimeMilliSeconds(time));
+                                             getLevelName(), toDateTimeMilliSeconds(time));
         }
     }
 
@@ -68,14 +68,8 @@ namespace armarx::armem
         return getInstance(id.instanceIndex);
     }
 
-    std::string EntitySnapshot::getLevelName() const
-    {
-        return "entity snapshot";
-    }
 
-    EntitySnapshot::ContainerT& EntitySnapshot::_underlyingContainer()
-    {
-        return instances;
-    }
+
+
 
 }
diff --git a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
index 182450dad748433d34f3c8406b4ef7221289313b..ab607b09ce7e1eeb073172ad36f88bdc6c2158b4 100644
--- a/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
+++ b/source/RobotAPI/libraries/armem/memory/EntitySnapshot.h
@@ -7,6 +7,7 @@
 #include "../core/MemoryID.h"
 
 #include "EntityData.h"
+#include "detail/MemoryLevel.h"
 #include "detail/MemoryContainer.h"
 
 
@@ -16,7 +17,9 @@ namespace armarx::armem
     /**
      * @brief Data of an entity at one point in time.
      */
-    class EntitySnapshot : public detail::MemoryContainer<std::vector<EntityDataPtr>>
+    class EntitySnapshot :
+        public detail::MemoryLevel,
+        public detail::MemoryContainer<std::vector<EntityDataPtr>>
     {
     public:
 
@@ -56,11 +59,23 @@ namespace armarx::armem
 
 
 
-        // MemoryContainer interface
+        // MemoryLevel interface
     public:
-        std::string getLevelName() const override;
+        std::string getKeyString() const override
+        {
+            return toDateTimeMilliSeconds(time);
+        }
+        std::string getLevelName() const override
+        {
+            return "entity snapshot";
+        }
+
+        // MemoryContainer interface
     protected:
-        ContainerT& _underlyingContainer() override;
+        ContainerT& _underlyingContainer() override
+        {
+            return instances;
+        }
 
     };
 
diff --git a/source/RobotAPI/libraries/armem/memory/Memory.cpp b/source/RobotAPI/libraries/armem/memory/Memory.cpp
index 8f80ba8b61c77f6c615ff4549af424e28be0105d..40b11cf18dd36095ac2f441f90c9c8499aeca6a8 100644
--- a/source/RobotAPI/libraries/armem/memory/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/memory/Memory.cpp
@@ -57,14 +57,14 @@ namespace armarx::armem
         }
         else
         {
-            throw armem::error::MissingEntry("core segment", name, "memory", this->name);
+            throw armem::error::MissingEntry("core segment", name, getLevelName(), this->name);
         }
     }
 
 
     const Entity& Memory::getEntity(const MemoryID& id) const
     {
-        checkStorageName(id.memoryName, this->name, "memory");
+        checkStorageName(id.memoryName, this->name, getLevelName());
         return getCoreSegment(id.coreSegmentName).getEntity(id);
     }
 
@@ -82,7 +82,7 @@ namespace armarx::armem
     {
         if (coreSegments.count(name) > 0)
         {
-            throw armem::error::StorageEntryAlreadyExists("core segment", name, "memory", this->name);
+            throw armem::error::StorageEntryAlreadyExists("core segment", name, getLevelName(), this->name);
         }
         auto it = coreSegments.emplace(coreSegment->name, std::move(coreSegment)).first;
         ARMARX_CHECK_NOT_NULL(it->second);
@@ -109,7 +109,7 @@ namespace armarx::armem
 
     MemoryID Memory::update(const InternalEntityUpdate& update)
     {
-        checkStorageName(update.entityID.memoryName, this->name, "memory");
+        checkStorageName(update.entityID.memoryName, this->name, getLevelName());
 
         auto it = this->coreSegments.find(update.entityID.coreSegmentName);
         if (it != coreSegments.end())
@@ -119,14 +119,9 @@ namespace armarx::armem
         else
         {
             throw armem::error::MissingEntry("core segment", update.entityID.coreSegmentName,
-                                             "memory", name);
+                                             getLevelName(), name);
         }
     }
 
-    void Memory::clear()
-    {
-        coreSegments.clear();
-    }
-
 
 }
diff --git a/source/RobotAPI/libraries/armem/memory/Memory.h b/source/RobotAPI/libraries/armem/memory/Memory.h
index 456114f5792935d3e3007fb582927f98e3be1fda..f8895e12389326fb2a270c5c0665ed2755ab8284 100644
--- a/source/RobotAPI/libraries/armem/memory/Memory.h
+++ b/source/RobotAPI/libraries/armem/memory/Memory.h
@@ -64,9 +64,6 @@ namespace armarx::armem
         virtual MemoryID update(const InternalEntityUpdate& update) override;
         using EntityStorage::update;
 
-        /// Clear the core segments.
-        void clear() override;
-
         /// Get an cleared copy of `*this` (without core segments).
         MemoryPtr getEmptyCopy() const;
 
@@ -76,12 +73,14 @@ namespace armarx::armem
         std::map<std::string, CoreSegmentPtr> coreSegments;
 
 
-        // MemoryContainer interface
+        // MemoryLevel interface
     public:
         std::string getLevelName() const override
         {
             return "memory";
         }
+
+        // MemoryContainer interface
     protected:
         ContainerT& _underlyingContainer() override
         {
diff --git a/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
index d78bf742815b34f84e59d7e0e60bcc8db0918075..23400ca9e54d74b7b60df32a8770de9d8a937606 100644
--- a/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
+++ b/source/RobotAPI/libraries/armem/memory/ProviderSegment.cpp
@@ -58,19 +58,19 @@ namespace armarx::armem
         }
         else
         {
-            throw error::MissingEntry("entity", name, "provider segment", this->name);
+            throw error::MissingEntry("entity", name, getLevelName(), this->name);
         }
     }
 
     const Entity& ProviderSegment::getEntity(const MemoryID& id) const
     {
-        checkStorageName(id.providerSegmentName, this->name, "provider segment");
+        checkStorageName(id.providerSegmentName, this->name, getLevelName());
         return getEntity(id.entityName);
     }
 
     MemoryID ProviderSegment::update(const InternalEntityUpdate& update)
     {
-        checkStorageName(update.entityID.providerSegmentName, this->name, "provider segment");
+        checkStorageName(update.entityID.providerSegmentName, this->name, getLevelName());
 
         auto it = this->entities.find(update.entityID.providerSegmentName);
         if (it == entities.end())
@@ -100,11 +100,6 @@ namespace armarx::armem
         return *it->second;
     }
 
-    void ProviderSegment::clear()
-    {
-        entities.clear();
-    }
-
     void ProviderSegment::setMaxHistorySize(long maxSize)
     {
         this->maxHistorySize = maxSize;
diff --git a/source/RobotAPI/libraries/armem/memory/ProviderSegment.h b/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
index 07580d23ee1a111d31c7f2acca06487491a1f2ab..217ef4f097aa1d1db7c413233f5022d53798b645 100644
--- a/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
+++ b/source/RobotAPI/libraries/armem/memory/ProviderSegment.h
@@ -56,8 +56,6 @@ namespace armarx::armem
         /// Move and insert an entity.
         Entity& addEntity(EntityPtr&& entity);
 
-        /// Clear the entities.
-        virtual void clear() override;
         /// Get an cleared copy of `*this` (without entities).
         ProviderSegmentPtr getEmptyCopy() const;
 
@@ -82,12 +80,14 @@ namespace armarx::armem
         long maxHistorySize = -1;
 
 
-        // MemoryContainer interface
+        // MemoryLevel interface
     public:
         std::string getLevelName() const override
         {
             return "provider segment";
         }
+
+        // MemoryContainer interface
     protected:
         ContainerT& _underlyingContainer() override
         {
diff --git a/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.cpp b/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.cpp
index f3637c1ac93db1792c22b42a6624d41d7599cc83..88e3dcfef5466022c8e1887f41f4b5d7b045a0f0 100644
--- a/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.cpp
+++ b/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.cpp
@@ -54,6 +54,11 @@ namespace armarx::armem::detail
         }
     }
 
+    string EntityStorage::getKeyString() const
+    {
+        return name;
+    }
+
     void EntityStorage::checkStorageName(const std::string& expectedName, const std::string& actualName,
                                          const std::string& storageTerm)
     {
diff --git a/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.h b/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.h
index 25024e02273936aa9060cc69189793da051b2c6f..ef69c1d6fc9423c63b862c355c7c9fd9b8849c45 100644
--- a/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.h
+++ b/source/RobotAPI/libraries/armem/memory/detail/EntityStorage.h
@@ -4,6 +4,7 @@
 
 #include "../Entity.h"
 #include "../EntitySnapshot.h"
+#include "MemoryLevel.h"
 
 
 namespace armarx::armem::detail
@@ -14,14 +15,14 @@ namespace armarx::armem::detail
      *
      * Can be updated by multiple entity updates.
      */
-    class EntityStorage
+    class EntityStorage : public MemoryLevel
     {
     public:
 
         EntityStorage();
         EntityStorage(const std::string& name);
 
-        virtual ~EntityStorage();
+        virtual ~EntityStorage() override;
 
 
         /**
@@ -37,9 +38,6 @@ namespace armarx::armem::detail
          */
         virtual MemoryID update(const InternalEntityUpdate& update) = 0;
 
-        /// Clear this storage of any elements.
-        virtual void clear() = 0;
-
 
         /**
          * @brief Retrieve an entity.
@@ -63,6 +61,9 @@ namespace armarx::armem::detail
         virtual const EntitySnapshot& getEntitySnapshot(const MemoryID& id) const;
 
 
+        /// Return `name`.
+        virtual std::string getKeyString() const override;
+
 
     protected:
 
@@ -78,6 +79,9 @@ namespace armarx::armem::detail
     };
 
 
+    /**
+     * @brief An entity storage with a specific (Aron) type.
+     */
     class TypedEntityStorage : public EntityStorage
     {
     public:
diff --git a/source/RobotAPI/libraries/armem/memory/detail/MemoryContainer.h b/source/RobotAPI/libraries/armem/memory/detail/MemoryContainer.h
index ac73ca0a7937b90cc22b4b7884ddc6e483480420..e1f5c1143cdfcb779c6b4ce1c0989d83116dbc46 100644
--- a/source/RobotAPI/libraries/armem/memory/detail/MemoryContainer.h
+++ b/source/RobotAPI/libraries/armem/memory/detail/MemoryContainer.h
@@ -7,7 +7,10 @@ namespace armarx::armem::detail
 {
 
     /**
-     * @brief A container of entities at some point in the hierarchy.
+     * @brief A memory container at some point in the hierarchy.
+     *
+     * This class containes some convenience functions to allow more uniform
+     * access to the different memory levels.
      */
     template <class _ContainerT>
     class MemoryContainer
@@ -17,18 +20,10 @@ namespace armarx::armem::detail
 
     public:
 
-        MemoryContainer()
-        {}
-
         virtual ~MemoryContainer()
         {}
 
 
-        // Introspection
-
-        virtual std::string getLevelName() const = 0;
-
-
         // Container methods
 
         virtual bool empty() const
@@ -39,6 +34,10 @@ namespace armarx::armem::detail
         {
             return _underlyingContainer().size();
         }
+        virtual void clear()
+        {
+            return _underlyingContainer().clear();
+        }
 
         auto begin() const
         {
diff --git a/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.cpp b/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3fa1ea96e2bc95de4647418858ad52462b1c36bd
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.cpp
@@ -0,0 +1,10 @@
+#include "MemoryLevel.h"
+
+
+namespace armarx::armem::detail
+{
+
+    MemoryLevel::~MemoryLevel()
+    {}
+
+}
diff --git a/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.h b/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.h
new file mode 100644
index 0000000000000000000000000000000000000000..6516eb4b0ca93fa61305533c5cc429a59bed860b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/memory/detail/MemoryLevel.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <string>
+
+
+namespace armarx::armem::detail
+{
+
+    /**
+     * @brief Base class of memory classes on different levels.
+     */
+    class MemoryLevel
+    {
+    public:
+
+        virtual ~MemoryLevel();
+
+
+        // Introspection
+
+        /// Get a string version of `*this`' key.
+        virtual std::string getKeyString() const = 0;
+
+        /// Get a readable name of this level for messages, errors etc.
+        virtual std::string getLevelName() const = 0;
+
+    };
+
+}