diff --git a/algo/base/Options.h b/algo/base/Options.h
index 1f53cf98516bb914d69294dbdacd55a4631c45ac..711d97c7c0caa5f479ec32a8fdc9bdba434ee182 100644
--- a/algo/base/Options.h
+++ b/algo/base/Options.h
@@ -4,6 +4,9 @@
 #ifndef CBM_ALGO_BASE_OPTIONS_H
 #define CBM_ALGO_BASE_OPTIONS_H
 
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/version.hpp>
+
 #include <set>
 #include <string>
 #include <vector>
@@ -48,7 +51,7 @@ namespace cbm::algo
     }
 
 
-  private:
+  private:                   // members
     std::string fParamsDir;  // TODO: can we make this a std::path?
     std::string fInputLocator;
     std::string fOutputFile;
@@ -63,6 +66,28 @@ namespace cbm::algo
     std::vector<Step> fRecoSteps;
     std::vector<RecoData> fOutputTypes;
     std::vector<fles::Subsystem> fDetectors;
+
+  private:  // serialization
+    friend class boost::serialization::access;
+
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& fParamsDir;
+      ar& fInputLocator;
+      ar& fOutputFile;
+      ar& fSplitOutputPerTS;
+      ar& fLogLevel;
+      ar& fLogFile;
+      ar& fDevice;
+      ar& fMonitorUri;
+      ar& fCollectKernelTimes;
+      ar& fNumTimeslices;
+      ar& fSkipTimeslices;
+      ar& fRecoSteps;
+      ar& fOutputTypes;
+      ar& fDetectors;
+    }
   };
 
 }  // namespace cbm::algo
diff --git a/algo/global/Archive.cxx b/algo/global/Archive.cxx
index 9a2c1fa69afba8158d63c502b7e8f5d33835cc9d..00cd02514ae2aec50b791c68355c7eae1830290e 100644
--- a/algo/global/Archive.cxx
+++ b/algo/global/Archive.cxx
@@ -3,7 +3,7 @@
    Authors: Felix Weiglhofer [committer] */
 #include "Archive.h"
 
-#include "CbmStsDigi.h"
+#include "CbmDigiEvent.h"
 
 #include <boost/algorithm/string.hpp>
 #include <boost/archive/binary_iarchive.hpp>
diff --git a/algo/global/Archive.h b/algo/global/Archive.h
index c3f05df94a3fb68492da3c3b448620d795da00be..1c6289f2d7d9fe2260bef1d848e1081976892026 100644
--- a/algo/global/Archive.h
+++ b/algo/global/Archive.h
@@ -12,6 +12,7 @@
 #include <optional>
 #include <vector>
 
+#include "ArchiveDescriptor.h"
 #include "RecoIO.h"
 #include "compat/Filesystem.h"
 
@@ -27,7 +28,7 @@ namespace cbm::algo
     /**
      * @brief Construct empty archive.
     */
-    Archive(const std::vector<fles::SubsystemIdentifier>& detectors) : fDetectors(detectors) {}
+    Archive(ArchiveDescriptor descriptor) : fDescriptor(descriptor) {}
     ~Archive() = default;
 
     /**
@@ -35,20 +36,20 @@ namespace cbm::algo
     */
     void Store(fs::path file, std::optional<size_t> tsId = {}) const;
 
-    const std::vector<fles::SubsystemIdentifier>& Detectors() const { return fDetectors; }
+    const ArchiveDescriptor& Descriptor() const { return fDescriptor; }
 
     std::vector<RecoIO>& TimesliceResults() { return fTimesliceResults; }
     const std::vector<RecoIO>& TimesliceResults() const { return fTimesliceResults; }
 
   private:
-    std::vector<fles::SubsystemIdentifier> fDetectors;
+    ArchiveDescriptor fDescriptor;
     std::vector<RecoIO> fTimesliceResults;
 
     friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive& ar, const unsigned int /*version*/)
     {
-      ar& fDetectors;
+      ar& fDescriptor;
       ar& fTimesliceResults;
     }
 
diff --git a/algo/global/ArchiveDescriptor.h b/algo/global/ArchiveDescriptor.h
new file mode 100644
index 0000000000000000000000000000000000000000..64c3ecedacde1e51c1cddd589ed05ed0e46398d8
--- /dev/null
+++ b/algo/global/ArchiveDescriptor.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+#ifndef CBM_ALGO_GLOBAL_ARCHIVE_DESCRIPTOR_H
+#define CBM_ALGO_GLOBAL_ARCHIVE_DESCRIPTOR_H
+
+#include "System.hpp"
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/version.hpp>
+
+#include <chrono>
+#include <string>
+
+namespace cbm::algo
+{
+
+  class ArchiveDescriptor {
+
+  public:
+    ArchiveDescriptor()
+      : fTimeCreated(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))
+      , fHostname(fles::system::current_hostname())
+      , fUsername(fles::system::current_username())
+    {
+    }
+
+    std::time_t TimeCreated() const { return fTimeCreated; }
+    const std::string& Hostname() const { return fHostname; }
+    const std::string& Username() const { return fUsername; }
+
+  private:  // members
+    std::time_t fTimeCreated = std::time_t();
+    std::string fHostname;
+    std::string fUsername;
+
+  private:  // serialization
+    friend class boost::serialization::access;
+
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& fTimeCreated;
+      ar& fHostname;
+      ar& fUsername;
+    }
+  };
+
+}  // namespace cbm::algo
+
+#endif  // CBM_ALGO_GLOBAL_ARCHIVE_DESCRIPTOR_H
diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx
index 637ed89fa3721af78bd5ff518bd3a49bd9f01e7b..cbae1377c9a5fc409929dda30079541c7f3b7677 100644
--- a/algo/global/Reco.cxx
+++ b/algo/global/Reco.cxx
@@ -3,6 +3,8 @@
    Authors: Felix Weiglhofer [committer] */
 #include "Reco.h"
 
+#include "CbmDigiEvent.h"
+
 #include <Monitor.hpp>
 #include <System.hpp>
 
@@ -86,8 +88,7 @@ RecoIO Reco::Run(const fles::Timeslice& ts)
   L_(info) << ">>> Processing TS " << ts.index();
   xpu::set<cbm::algo::Params>(Params());
 
-  std::vector<CbmStsDigi> digis;
-
+  CbmDigiTimeslice digiTs;
   if (Opts().HasStep(Step::Unpack)) {
     switch (Params().sts.unpackMode) {
       case RecoParams::UnpackMode::XPU:
@@ -95,11 +96,11 @@ RecoIO Reco::Run(const fles::Timeslice& ts)
         throw std::runtime_error("XPU unpacker currently not implemented");
         break;
       default:
-      case RecoParams::UnpackMode::CPU: digis = fUnpack.Run(ts).first.fData.fSts.fDigis; break;
+      case RecoParams::UnpackMode::CPU: digiTs = fUnpack.Run(ts).first; break;
     }
   }
-
-  if (Opts().HasStep(Step::LocalReco) && Opts().HasDetector(fles::Subsystem::STS)) fStsHitFinder(digis);
+  if (Opts().HasStep(Step::LocalReco) && Opts().HasDetector(fles::Subsystem::STS))
+    fStsHitFinder(digiTs.fData.fSts.fDigis);
 
   xpu::timings ts_times = xpu::pop_timer();
 
@@ -110,8 +111,10 @@ RecoIO Reco::Run(const fles::Timeslice& ts)
 
   PrintTimings(ts_times);
 
-  RecoIO results;
-  results.StsDigis() = std::move(digis);
+  RecoIO results(RecoResultsDescriptor(Opts(), Params()));
+  CbmDigiEvent ev;
+  ev.fData = std::move(digiTs.fData);
+  results.Events().emplace_back(std::move(ev));
 
   return results;
 }
diff --git a/algo/global/RecoIO.cxx b/algo/global/RecoIO.cxx
index aae34693010200443f7ef99e6b4b281448790e2c..10599bae7cf6dec1bd1e796f20fbf1c53d302f13 100644
--- a/algo/global/RecoIO.cxx
+++ b/algo/global/RecoIO.cxx
@@ -3,9 +3,10 @@
    Authors: Felix Weiglhofer [committer] */
 #include "RecoIO.h"
 
-#include "CbmStsDigi.h"
+#include "CbmDigiEvent.h"
 
 using namespace cbm::algo;
 
+RecoIO::RecoIO(RecoResultsDescriptor descriptor) : fDescriptor(descriptor) {}
 RecoIO::RecoIO() {}
 RecoIO::~RecoIO() {}
diff --git a/algo/global/RecoIO.h b/algo/global/RecoIO.h
index fab2837b3041737cd0942db9dd8b2476c36efe6c..9d6630e9ea3df305c635579452e82fac0ecb5af5 100644
--- a/algo/global/RecoIO.h
+++ b/algo/global/RecoIO.h
@@ -8,7 +8,10 @@
 
 #include <vector>
 
+#include "RecoResultsDescriptor.h"
+
 class CbmStsDigi;
+class CbmDigiEvent;
 namespace cbm::algo::sts
 {
   using Digi = CbmStsDigi;
@@ -20,20 +23,25 @@ namespace cbm::algo
 
   public:
     // Place ctor / dtor in cxx, so that we can forward-declare the data classes and keep this header small.
-    RecoIO();
+    RecoIO(RecoResultsDescriptor descriptor);
     ~RecoIO();
 
-    std::vector<sts::Digi>& StsDigis() { return fStsDigis; }
-    const std::vector<sts::Digi>& StsDigis() const { return fStsDigis; }
+    const RecoResultsDescriptor& Descriptor() const { return fDescriptor; }
+    const std::vector<CbmDigiEvent>& Events() const { return fEvents; }
+    std::vector<CbmDigiEvent>& Events() { return fEvents; }
 
   private:
-    std::vector<sts::Digi> fStsDigis;
+    RecoResultsDescriptor fDescriptor;
+    std::vector<CbmDigiEvent> fEvents;
 
     friend class boost::serialization::access;
+
+    RecoIO();
+
     template<class Archive>
     void serialize(Archive& ar, const unsigned int /*version*/)
     {
-      ar& fStsDigis;
+      ar& fEvents;
     }
   };
 }  // namespace cbm::algo
diff --git a/algo/global/RecoResultsDescriptor.h b/algo/global/RecoResultsDescriptor.h
new file mode 100644
index 0000000000000000000000000000000000000000..39bba9a972f042c1e45647b158f41cab9dfbf5d2
--- /dev/null
+++ b/algo/global/RecoResultsDescriptor.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+#ifndef CBM_ALGO_GLOBAL_RECO_RESULTS_DESCRIPTOR_H
+#define CBM_ALGO_GLOBAL_RECO_RESULTS_DESCRIPTOR_H
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/version.hpp>
+
+#include "Options.h"
+#include "RecoParams.h"
+#include "config/Yaml.h"
+
+namespace cbm::algo
+{
+  class RecoIO;
+}
+
+namespace cbm::algo
+{
+  class RecoResultsDescriptor {
+  public:
+    RecoResultsDescriptor(Options options, RecoParams params) : fOptions(options), fParams(params) {}
+
+    const RecoParams& Params() const { return fParams; }
+    const Options& Opts() const { return fOptions; }
+
+  private:  // members
+    Options fOptions;
+    RecoParams fParams;
+
+  private:  // serialization
+    friend class boost::serialization::access;
+    friend class RecoIO;
+
+    RecoResultsDescriptor() = default;
+
+    template<class Archive>
+    void save(Archive& ar, const unsigned int /*version*/) const
+    {
+      ar& fOptions;
+      std::string yaml = config::Dump()(fParams);
+      ar& yaml;
+    }
+
+    template<class Archive>
+    void load(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& fOptions;
+      std::string yaml;
+      ar& yaml;
+      auto node = YAML::Load(yaml);
+      fParams   = config::Read<RecoParams>(node);
+    }
+  };
+}  // namespace cbm::algo
+
+#endif  // CBM_ALGO_GLOBAL_RECO_RESULTS_DESCRIPTOR_H
diff --git a/reco/app/cbmreco/main.cxx b/reco/app/cbmreco/main.cxx
index 1bfd1674a9f1724ddd7b9e634125fdc3b444a26d..7edd4a4cb684c8ca67a2be6c9e01db2a4dcfe2d0 100644
--- a/reco/app/cbmreco/main.cxx
+++ b/reco/app/cbmreco/main.cxx
@@ -1,6 +1,8 @@
 /* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Felix Weiglhofer [committer] */
+#include "CbmDigiEvent.h"
+
 #include <TimesliceAutoSource.hpp>
 
 #include <log.hpp>
@@ -46,7 +48,7 @@ int main(int argc, char** argv)
   reco.Init(opts);
 
 
-  Archive archive({fles::SubsystemIdentifier::STS});  // TODO: use opts.Detector() once detector flag is merged
+  Archive archive(ArchiveDescriptor {});  // TODO: use opts.Detector() once detector flag is merged
   fles::TimesliceAutoSource source {opts.InputLocator()};
   int tsIdx  = 0;
   int num_ts = opts.NumTimeslices();
@@ -59,7 +61,7 @@ int main(int argc, char** argv)
     auto result = reco.Run(*ts);
 
     if (opts.SplitOutputPerTS() && !opts.OutputFile().empty()) {
-      Archive tsResults({fles::SubsystemIdentifier::STS});  // TODO: use opts.Detector() once detector flag is merged
+      Archive tsResults(ArchiveDescriptor {});  // TODO: use opts.Detector() once detector flag is merged
       tsResults.TimesliceResults().emplace_back(std::move(result));
       tsResults.Store(opts.OutputFile(), ts->index());
     }