diff --git a/objectstore/Action.hpp b/objectstore/Action.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..59a45634f81b81f2fdfd3b0bfdccde6295cd8e6a
--- /dev/null
+++ b/objectstore/Action.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+class Action {
+public:
+  void execute() {}
+};
\ No newline at end of file
diff --git a/objectstore/Agent.cpp b/objectstore/Agent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2fca9ee5b0018fa0c0f0cd10f32c8bf4b298bd9f
--- /dev/null
+++ b/objectstore/Agent.cpp
@@ -0,0 +1,235 @@
+#include "Agent.hpp"
+#include "AgentRegister.hpp"
+#include "RootEntry.hpp"
+#include <string>
+#include <sstream>
+#include <sys/syscall.h>
+#include <ctime>
+
+Agent::Agent(ObjectStore & os): 
+  ObjectOps<cta::objectstore::Agent>(os), 
+  m_nextId(0), m_setupDone(false), m_creationDone(false), m_observerVersion(false) {};
+
+Agent::Agent(ObjectStore & os, const std::string & typeName): 
+  ObjectOps<cta::objectstore::Agent>(os), 
+  m_nextId(0), m_setupDone(false), m_creationDone(false), m_observerVersion(false) {
+  setup(typeName);
+}
+
+// Passive constructor, used for looking at existing agent records
+Agent::Agent(const std::string & name, Agent & agent):
+  ObjectOps<cta::objectstore::Agent>(agent.objectStore(), name),
+  m_nextId(0), m_setupDone(true), m_creationDone(true), m_observerVersion(true)
+{
+  // check the presence of the entry
+  cta::objectstore::Agent as;
+  updateFromObjectStore(as, agent.getFreeContext());
+}
+
+void Agent::setup(const std::string & typeName) {
+  std::stringstream aid;
+  // Get time
+  time_t now = time(0);
+  struct tm localNow;
+  localtime_r(&now, &localNow);
+  // Get hostname
+  char host[200];
+  cta::exception::Errnum::throwOnMinusOne(gethostname(host, sizeof(host)),
+    "In AgentId::AgentId:  failed to gethostname");
+  // gettid is a safe system call (never fails)
+  aid << typeName << "-" << host << "-" << syscall(SYS_gettid) << "-"
+    << 1900 + localNow.tm_year
+    << std::setfill('0') << std::setw(2) 
+    << 1 + localNow.tm_mon
+    << localNow.tm_mday << "-"
+    << localNow.tm_hour << ":"
+    << localNow.tm_min << ":"
+    << localNow.tm_sec;
+  ObjectOps<cta::objectstore::Agent>::setName(aid.str());
+  m_setupDone = true;
+}
+
+void Agent::create() {
+  if (!m_setupDone)
+    throw SetupNotDone("In Agent::create(): setup() not yet done");
+  RootEntry re(*this);
+  AgentRegister ar(re.allocateOrGetAgentRegister(*this), *this);
+  ar.addIntendedElement(selfName(), *this);
+  cta::objectstore::Agent as;
+  as.set_name(selfName());
+  writeChild(selfName(), as);
+  ar.upgradeIntendedElementToActual(selfName(), *this);
+  m_creationDone = true;
+}
+
+std::string Agent::type() {
+  if (!m_setupDone)
+    throw SetupNotDone("In Agent::type(): setup() not yet done");
+  return m_typeName;
+}
+
+std::string Agent::name() {
+  if (!m_setupDone)
+    throw SetupNotDone("In Agent::name(): setup() not yet done");
+  return selfName();
+}
+
+Agent::~Agent() {
+  for (size_t i=0; i < c_handleCount; i++) {
+    m_contexts[i].release();
+  }
+  if (m_creationDone) {
+    try {
+      remove();
+      RootEntry re(*this);
+      AgentRegister ar(re.getAgentRegister(*this), *this);
+      ar.removeElement(selfName(),*this);
+    } catch(...) {}
+  }
+}
+
+std::string Agent::nextId(const std::string & childType) {
+  if (!m_setupDone)
+    throw SetupNotDone("In Agent::nextId(): setup() not yet done");
+  if (m_observerVersion)
+    throw ObserverOnly("In Agent::nextId(): this object is observer only");
+  std::stringstream id;
+  id << childType << "-" << name() << "-" << m_nextId++;
+  return id.str();
+}
+
+ContextHandleImplementation<myOS> & Agent::getFreeContext() {
+  for (size_t i=0; i < c_handleCount; i++) {
+    if (!m_contexts[i].isSet())
+      return m_contexts[i];
+  }
+  throw cta::exception::Exception("Could not find free context slot");
+}
+
+void Agent::addToIntend (std::string container, std::string name, std::string typeName) {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::addToIntend(): creation() not yet done");
+  cta::objectstore::Agent as;
+  ContextHandle & ctx = getFreeContext();
+  lockExclusiveAndRead(as, ctx);
+  cta::objectstore::ObjectCreationIntent * oca = 
+    as.mutable_creationintent()->Add();
+  oca->set_container(container);
+  oca->set_name(name);
+  oca->set_type(typeName);
+  write(as);
+  unlock(ctx);
+}
+
+void Agent::removeFromIntent (std::string container, std::string name, std::string typeName) {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::removeFromIntent(): creation() not yet done");
+  cta::objectstore::Agent as;
+  ContextHandle & ctx = getFreeContext();
+  lockExclusiveAndRead(as, ctx);
+  bool found;
+  do {
+    found = false;
+    for (int i=0; i<as.creationintent_size(); i++) {
+      if (container == as.creationintent(i).container() &&
+          name == as.creationintent(i).name() &&
+          typeName == as.creationintent(i).type()) {
+        found = true;
+        as.mutable_creationintent()->SwapElements(i, as.creationintent_size()-1);
+        as.mutable_creationintent()->RemoveLast();
+        break;
+      }
+    }
+  } while (found);
+  write(as);
+  unlock(ctx);
+}
+
+void Agent::addToOwnership(std::string name, std::string typeName) {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::addToOwnership(): creation() not yet done");
+  cta::objectstore::Agent as;
+  ContextHandle & ctx = getFreeContext();
+  lockExclusiveAndRead(as, ctx);
+  cta::objectstore::ObjectOwnershipIntent * ooi = 
+    as.mutable_ownershipintent()->Add();
+  ooi->set_name(name);
+  ooi->set_type(typeName);
+  write(as);
+  unlock(ctx);
+}
+
+void Agent::removeFromOwnership(std::string name, std::string typeName) {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::removeFromOwnership(): creation() not yet done");
+  cta::objectstore::Agent as;
+  ContextHandle & ctx = getFreeContext();
+  lockExclusiveAndRead(as, ctx);
+  bool found;
+  do {
+    found = false;
+    for (int i=0; i<as.ownershipintent_size(); i++) {
+      if (name == as.ownershipintent(i).name() &&
+          typeName == as.ownershipintent(i).type()) {
+        found = true;
+        as.mutable_creationintent()->SwapElements(i, as.ownershipintent_size()-1);
+        as.mutable_creationintent()->RemoveLast();
+        break;
+      }
+    }
+  } while (found);
+  write(as);
+  unlock(ctx);
+}
+
+std::list<Agent::intentEntry> Agent::getIntentLog() {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::getIntentLog(): creation() not yet done");
+  cta::objectstore::Agent as;
+  updateFromObjectStore(as, getFreeContext());
+  std::list<intentEntry> ret;
+  for (int i=0; i<as.creationintent_size(); i++) {
+    ret.push_back(intentEntry(as.creationintent(i).container(),
+                              as.creationintent(i).name(),
+                              as.creationintent(i).type()));
+  }
+  return ret;
+}
+
+std::list<Agent::ownershipEntry> Agent::getOwnershipLog() {
+  if (!m_creationDone)
+    throw CreationNotDone("In Agent::getOwnershipLog(): creation() not yet done");
+  cta::objectstore::Agent as;
+  updateFromObjectStore(as, getFreeContext());
+  std::list<ownershipEntry> ret;
+  for (int i=0; i<as.creationintent_size(); i++) {
+    ret.push_back(ownershipEntry(as.creationintent(i).name(),
+                                 as.creationintent(i).type()));
+  }
+  return ret;
+}
+
+ObjectStore & Agent::objectStore() {
+  return ObjectOps<cta::objectstore::Agent>::objectStore();
+}
+
+std::string Agent::dump(Agent & agent) {
+  cta::objectstore::Agent as;
+  updateFromObjectStore(as, agent.getFreeContext());
+  std::stringstream ret;
+  ret<< "<<<< Agent " << selfName() << " dump start" << std::endl
+    << "name=" << as.name()
+    << "Ownership intent size=" << as.ownershipintent_size() << std::endl;
+  for (int i=0; i<as.ownershipintent_size(); i++) {
+    ret << "ownershipIntent[" << i << "]: name=" << as.ownershipintent(i).name() 
+        << " type=" << as.ownershipintent(i).type() << std::endl;
+  }
+  ret << "Creation intent size=" << as.creationintent_size() << std::endl;
+  for (int i=0; i<as.creationintent_size(); i++) {
+    ret << "creationIntent[" << i << "]: name=" << as.creationintent(i).name() 
+        << " type=" << as.creationintent(i).type() 
+        << " container=" << as.creationintent(i).container() << std::endl;
+  }
+  ret<< ">>>> AgentRegister " << selfName() << " dump end" << std::endl;
+  return ret.str();
+}
\ No newline at end of file
diff --git a/objectstore/Agent.hpp b/objectstore/Agent.hpp
index 782e5cc813fd25224a682b9cad034d5d6b080d8e..72a6e696c8e0e84b57b8f5b89ee7afce7fd358c6 100644
--- a/objectstore/Agent.hpp
+++ b/objectstore/Agent.hpp
@@ -20,6 +20,8 @@ public:
   
   Agent(ObjectStore & os, const std::string & typeName);
   
+  Agent(const std::string & name, Agent & agent);
+  
   void setup(const std::string & typeName);
   
   class SetupNotDone: public cta::exception::Exception {
@@ -32,6 +34,11 @@ public:
     CreationNotDone(const std::string & w): cta::exception::Exception(w) {}
   };
   
+  class ObserverOnly: public cta::exception::Exception {
+  public:
+    ObserverOnly(const std::string & w): cta::exception::Exception(w) {}
+  };
+  
   void create();
   
   std::string type();
@@ -76,10 +83,13 @@ public:
   
   ObjectStore & objectStore();
   
+  std::string dump(Agent & agent);
+  
 private:
   std::string m_typeName;
   bool m_setupDone;
   bool m_creationDone;
+  bool m_observerVersion;
   uint64_t m_nextId;
   static const size_t c_handleCount = 100;
   ContextHandleImplementation<myOS> m_contexts[c_handleCount];
diff --git a/objectstore/AgentRegister.cpp b/objectstore/AgentRegister.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4bcda54d164953abd93a324bd318402fdc3c2875
--- /dev/null
+++ b/objectstore/AgentRegister.cpp
@@ -0,0 +1,118 @@
+#include "AgentRegister.hpp"
+
+AgentRegister::AgentRegister(const std::string & name, Agent & agent):
+ObjectOps<cta::objectstore::AgentRegister>(agent.objectStore(), name) {
+  // Check that the entry is present and readable (depending on implementation
+  // of object store, locking might or might not succeed)
+  cta::objectstore::AgentRegister rs;
+  updateFromObjectStore(rs, agent.getFreeContext());
+}
+
+void AgentRegister::addElement (std::string name, Agent & agent) {
+  cta::objectstore::AgentRegister rs;
+  ContextHandle & context = agent.getFreeContext();
+  lockExclusiveAndRead(rs, context);
+  rs.add_elements(name);
+  write(rs);
+  unlock(context);
+}
+
+void AgentRegister::removeElement (const std::string  & name, Agent & agent) {
+  cta::objectstore::AgentRegister rs;
+  ContextHandle & context = agent.getFreeContext();
+  lockExclusiveAndRead(rs, context);
+  bool found;
+  do {
+    found = false;
+    for (int i=0; i<rs.elements_size(); i++) {
+      if (name == rs.elements(i)) {
+        found = true;
+        rs.mutable_elements()->SwapElements(i, rs.elements_size()-1);
+        rs.mutable_elements()->RemoveLast();
+        break;
+      }
+    }
+  } while (found);
+  write(rs);
+  unlock(context);
+}
+
+void AgentRegister::addIntendedElement(std::string name, Agent& agent) {
+  cta::objectstore::AgentRegister rs;
+  ContextHandle & context = agent.getFreeContext();
+  lockExclusiveAndRead(rs, context);
+  rs.add_intendedelements(name);
+  write(rs);
+  unlock(context);
+}
+
+void AgentRegister::upgradeIntendedElementToActual(std::string name, Agent& agent) {
+  cta::objectstore::AgentRegister rs;
+  ContextHandle & context = agent.getFreeContext();
+  lockExclusiveAndRead(rs, context);
+  bool found;
+  do {
+    found = false;
+    for (int i=0; i<rs.intendedelements_size(); i++) {
+      if (name == rs.intendedelements(i)) {
+        found = true;
+        rs.mutable_intendedelements()->SwapElements(i, rs.intendedelements_size()-1);
+        rs.mutable_intendedelements()->RemoveLast();
+        break;
+      }
+    }
+  } while (found);
+  rs.add_elements(name);
+  write(rs);
+  unlock(context);
+}
+
+
+void AgentRegister::removeIntendedElement(const std::string& name, Agent& agent) {
+  cta::objectstore::AgentRegister rs;
+  ContextHandle & context = agent.getFreeContext();
+  lockExclusiveAndRead(rs, context);
+  bool found;
+  do {
+    found = false;
+    for (int i=0; i<rs.intendedelements_size(); i++) {
+      if (name == rs.intendedelements(i)) {
+        found = true;
+        rs.mutable_intendedelements()->SwapElements(i, rs.intendedelements_size()-1);
+        rs.mutable_intendedelements()->RemoveLast();
+        break;
+      }
+    }
+  } while (found);
+  write(rs);
+  unlock(context);
+}
+
+
+
+std::list<std::string> AgentRegister::getElements(Agent & agent) {
+  cta::objectstore::AgentRegister rs;
+  updateFromObjectStore(rs, agent.getFreeContext());
+  std::list<std::string> ret;
+  for (int i=0; i<rs.elements_size(); i++) {
+    ret.push_back(rs.elements(i));
+  }
+  return ret;
+}
+
+std::string AgentRegister::dump(const std::string & title, Agent & agent) {
+  cta::objectstore::AgentRegister rs;
+  updateFromObjectStore(rs, agent.getFreeContext());
+  std::stringstream ret;
+  ret<< "<<<< AgentRegister " << title << " dump start" << std::endl
+    << "Array size=" << rs.elements_size() << std::endl;
+  for (int i=0; i<rs.elements_size(); i++) {
+    ret << "element[" << i << "]=" << rs.elements(i) << std::endl;
+  }
+  ret << "Intent array size=" << rs.intendedelements_size() << std::endl;
+  for (int i=0; i<rs.intendedelements_size(); i++) {
+    ret << "intendedElement[" << i << "]=" << rs.intendedelements(i) << std::endl;
+  }
+  ret<< ">>>> AgentRegister " << title << " dump end" << std::endl;
+  return ret.str();
+}
\ No newline at end of file
diff --git a/objectstore/AgentRegister.hpp b/objectstore/AgentRegister.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..da84b72d124fd024b94f5d7cae72d4edb998a695
--- /dev/null
+++ b/objectstore/AgentRegister.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "ObjectOps.hpp"
+#include "Agent.hpp"
+#include <algorithm>
+
+class AgentRegister: private ObjectOps<cta::objectstore::AgentRegister> {
+public:
+  AgentRegister(const std::string & name, Agent & agent);
+  void addElement (std::string name, Agent & agent);
+  void removeElement (const std::string  & name, Agent & agent);
+  void addIntendedElement (std::string name, Agent & agent);
+  void upgradeIntendedElementToActual(std::string name, Agent & agent);
+  void removeIntendedElement (const std::string  & name, Agent & agent);
+  std::list<std::string> getElements(Agent & agent);
+  std::string dump(const std::string & title, Agent & agent);
+};
\ No newline at end of file
diff --git a/objectstore/ObjectStoreChoice.hpp b/objectstore/ObjectStoreChoice.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..14e20225f83b2d0b9cb5b61b3b77a2d86082ef1e
--- /dev/null
+++ b/objectstore/ObjectStoreChoice.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+#include "ObjectOps.hpp"
+typedef ObjectStoreRados myOS;
\ No newline at end of file
diff --git a/objectstore/ObjectStructureDumper.hpp b/objectstore/ObjectStructureDumper.hpp
index d812b2bafbb3ec032c8c073a470a7f2eda46eead..b4a5b61407b254dc3133cd341c1b3e05e30a0b55 100644
--- a/objectstore/ObjectStructureDumper.hpp
+++ b/objectstore/ObjectStructureDumper.hpp
@@ -1,7 +1,8 @@
 #pragma once
 
 #include "RootEntry.hpp"
-#include "Register.hpp"
+#include "AgentRegister.hpp"
+#include "Agent.hpp"
 #include <iostream>
 
 class ObjectStrucutreDumper {
@@ -12,8 +13,13 @@ public:
     RootEntry re(agent);
     ret << re.dump(agent);
     try {
-      Register ar(re.getAgentRegister(agent), agent);
+      AgentRegister ar(re.getAgentRegister(agent), agent);
       ret << ar.dump("root->agentRegister", agent);
+      std::list<std::string> agList = ar.getElements(agent);
+      for (std::list<std::string>::iterator i=agList.begin(); i!=agList.end(); i++) {
+        Agent a(*i, agent);
+        ret << a.dump(agent);
+      }
     } catch (RootEntry::NotAllocatedEx &) {}
     ret << ">> Structure dump end" << std::endl;
     return ret.str();
diff --git a/objectstore/cta.proto b/objectstore/cta.proto
index cc21bd259006effa56f754b3b0ff4a26a92d2dfd..7bf0ff0c68e7485be85a62f35f462f4c7cc69575 100644
--- a/objectstore/cta.proto
+++ b/objectstore/cta.proto
@@ -6,11 +6,8 @@ message RootEntry {
   optional string agentregister = 1;
   repeated string agentregisterintentlog = 2;
   optional string jobpool = 3;
-  repeated string jobpoolintentlog = 4;
-  optional string driveregister = 5;
-  repeated string driveregisterintentlog = 6;
-  optional string taperegister = 7;
-  repeated string taperegisterintentlog = 8;
+  optional string driveregister = 4;
+  optional string taperegister = 5;
 }
 
 // The registers (simple name arrays)
diff --git a/objectstore/tapeResourceManagerTest.cpp b/objectstore/tapeResourceManagerTest.cpp
index 3c7fd760181aa9b97b1db3224ec0044d3563a501..72062fde30466bbd668adcb3dfe82f7acada4183 100644
--- a/objectstore/tapeResourceManagerTest.cpp
+++ b/objectstore/tapeResourceManagerTest.cpp
@@ -9,6 +9,7 @@
 #include "ContextHandle.hpp"
 #include "ObjectStructureDumper.hpp"
 #include "JobPool.hpp"
+#include "AgentRegister.hpp"
 
 
 
@@ -64,7 +65,7 @@ int main(void){
     // Get hold of the root entry
     RootEntry re(self);
     // Create and populate the job queues
-    Register agentRegister(re.allocateOrGetAgentRegister(self), self);
+    AgentRegister agentRegister(re.allocateOrGetAgentRegister(self), self);
     JobPool jobPool(re.allocateOrGetJobPool(self), self);
     // Dump again
     std::cout << osd.dump(self) << std::endl;