diff --git a/algo/base/AlgoTraits.h b/algo/base/AlgoTraits.h
index 21954e3030ff6ec514ab9cad56530ecaddffee78..ecd14f99a4f61e0152e969317dbe1f05c0a9b679 100644
--- a/algo/base/AlgoTraits.h
+++ b/algo/base/AlgoTraits.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <tuple>
 #include <type_traits>
 
 /**
@@ -42,19 +43,25 @@ namespace cbm::algo::algo_traits
   template<typename Algo>
   using ResultOf_t = typename detail::ResultOf<Algo>::type;
 
-  // Currently assume algorithms return std::pair<R, M>
-  // where R is the output and M is the monitoring data
+  // Currently assume algorithms return std::tuple<R, M, A>
+  // where R is the output, M is the monitoring data and A is auxiliary data
 
   /**
    * @brief Type alias for the output type produced by an algorithm
    */
   template<typename Algo>
-  using Output_t = typename ResultOf_t<Algo>::first_type;
+  using Output_t = typename std::tuple_element<0, ResultOf_t<Algo>>::type;
 
   /**
    * @brief Type alias for the monitoring type produced by an algorithm
    */
   template<typename Algo>
-  using Monitor_t = typename ResultOf_t<Algo>::second_type;
+  using Monitor_t = typename std::tuple_element<1, ResultOf_t<Algo>>::type;
+
+  /**
+   * @brief Type alias for the auxiliary data type produced by an algorithm
+   */
+  template<typename Algo>
+  using Aux_t = typename std::tuple_element<2, ResultOf_t<Algo>>::type;
 
 }  // namespace cbm::algo::algo_traits
diff --git a/algo/detectors/bmon/Unpack.h b/algo/detectors/bmon/Unpack.h
index 9535c560ec72e0eefa8d1e1edf61caa923f21bfe..0a35e0cd1b6a8e4b13a78f9f2a2a70abb6c84a5b 100644
--- a/algo/detectors/bmon/Unpack.h
+++ b/algo/detectors/bmon/Unpack.h
@@ -13,7 +13,7 @@ namespace cbm::algo::bmon
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmBmonDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmBmonDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/bmon/UnpackMS.cxx b/algo/detectors/bmon/UnpackMS.cxx
index da858f1519cce400adf0fee401a9f9146a0f50b3..c6a198f4f2a02400051eee0d2f5c3f49bf105e28 100644
--- a/algo/detectors/bmon/UnpackMS.cxx
+++ b/algo/detectors/bmon/UnpackMS.cxx
@@ -30,12 +30,12 @@ namespace cbm::algo::bmon
     // --- Number of messages in microslice
     auto msSize = msDescr.size;
     if (msSize % sizeof(critof001::Message) != 0) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
     const uint32_t numMessages = msSize / sizeof(critof001::Message);
     if (numMessages < 2) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
 
@@ -43,11 +43,11 @@ namespace cbm::algo::bmon
     auto message = reinterpret_cast<const critof001::Message*>(msContent);
 
     const uint32_t maxDigis = numMessages - 2;  // -2 for the TS_MSB and EPOCH messages
-    result.first.reserve(maxDigis);
+    std::get<0>(result).reserve(maxDigis);
 
     // --- The first message in the MS is expected to be of type EPOCH.
     if (message[0].getMessageType() != critof001::MSG_EPOCH) {
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
 
@@ -55,7 +55,7 @@ namespace cbm::algo::bmon
       const uint64_t msStartEpoch =
         static_cast<uint64_t>(msDescr.idx / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
       if (message[0].getGdpbEpEpochNb() != msStartEpoch) {
-        result.second.fNumErrInvalidStartEpoch++;
+        std::get<1>(result).fNumErrInvalidStartEpoch++;
         return result;
       }
     }
@@ -69,7 +69,7 @@ namespace cbm::algo::bmon
 
     // --- The last message in the MS is expected to be EndOfMs.
     if (!message[numMessages - 1].isEndOfMs()) {
-      result.second.fNumErrInvalidLastMessage++;
+      std::get<1>(result).fNumErrInvalidLastMessage++;
       return result;
     }
     //Check if last message is "EndOfMs"!! Maybe loop to messageNr < numMessages - 1
@@ -81,7 +81,7 @@ namespace cbm::algo::bmon
       switch (message[messageNr].getMessageType()) {
 
         case critof001::MSG_HIT: {
-          ProcessHitMessage(message[messageNr], time, result.first, result.second);
+          ProcessHitMessage(message[messageNr], time, std::get<0>(result), std::get<1>(result));
           break;
         }
         case critof001::MSG_EPOCH: {
@@ -89,15 +89,15 @@ namespace cbm::algo::bmon
           break;
         }
         case critof001::MSG_SLOWC: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
         case critof001::MSG_SYST: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
         default: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
       }  //? Message type
diff --git a/algo/detectors/bmon/UnpackMS.h b/algo/detectors/bmon/UnpackMS.h
index af37710afa5982280724b017fa0a3a77c6159949..9c893c5318222a63117868835e0620d530fe74ef 100644
--- a/algo/detectors/bmon/UnpackMS.h
+++ b/algo/detectors/bmon/UnpackMS.h
@@ -34,7 +34,7 @@ namespace cbm::algo::bmon
   /** @struct UnpackPar
    ** @author Volker Friese <v.friese@gsi.de>
    ** @since 25 November 2021
-   ** @brief Parameters required for the STS unpacking (specific to one component)
+   ** @brief Parameters required for the BMON unpacking (specific to one component)
    **/
   struct UnpackPar {
     std::vector<UnpackElinkPar> fElinkParams = {};  ///< Parameters for each eLink
@@ -44,7 +44,7 @@ namespace cbm::algo::bmon
   /** @struct UnpackMoni
    ** @author Volker Friese <v.friese@gsi.de>
    ** @since 2 December 2021
-   ** @brief Monitoring data for STS unpacking
+   ** @brief Monitoring data for BMON unpacking
    **/
   struct UnpackMonitorData {
     uint32_t fNumNonHitOrTsbMessage     = 0;
@@ -71,6 +71,14 @@ namespace cbm::algo::bmon
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
 
   /** @class Unpack
    ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de>
@@ -79,7 +87,7 @@ namespace cbm::algo::bmon
    ** @since 25 November 2021
    ** @brief Unpack algorithm for STS
    **/
-  class UnpackMS : public UnpackMSBase<CbmBmonDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmBmonDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct from parameters **/
diff --git a/algo/detectors/much/Unpack.h b/algo/detectors/much/Unpack.h
index 191d421f9639cab11a9f4c97080418bfc40ec1e6..b89719afb70dc9ce5ee9f456be2567baf8284459 100644
--- a/algo/detectors/much/Unpack.h
+++ b/algo/detectors/much/Unpack.h
@@ -13,7 +13,7 @@ namespace cbm::algo::much
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmMuchDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmMuchDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/much/UnpackMS.cxx b/algo/detectors/much/UnpackMS.cxx
index 1274de56bdb434c74c51120b921fa0c9a2117049..d917fa4cda746a5af02f8f2ff20485c4f755eb1c 100644
--- a/algo/detectors/much/UnpackMS.cxx
+++ b/algo/detectors/much/UnpackMS.cxx
@@ -45,30 +45,30 @@ namespace cbm::algo::much
     // --- Number of messages in microslice
     auto msSize = msDescr.size;
     if (msSize % sizeof(stsxyter::Message) != 0) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
     const uint32_t numMessages = msSize / sizeof(stsxyter::Message);
     if (numMessages < 2) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
 
     const uint32_t maxDigis = numMessages - 2;  // -2 for the TS_MSB and EPOCH messages
-    result.first.reserve(maxDigis);
+    std::get<0>(result).reserve(maxDigis);
 
     // --- Interpret MS content as sequence of SMX messages
     auto message = reinterpret_cast<const stsxyter::Message*>(msContent);
 
     // --- The first message in the MS is expected to be of type EPOCH and can be ignored.
     if (message[0].GetMessType() != stsxyter::MessType::Epoch) {
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
 
     // --- The second message must be of type ts_msb.
     if (message[1].GetMessType() != stsxyter::MessType::TsMsb) {
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
     ProcessTsmsbMessage(message[1], time);
@@ -80,7 +80,7 @@ namespace cbm::algo::much
       switch (message[messageNr].GetMessType()) {
 
         case stsxyter::MessType::Hit: {
-          ProcessHitMessage(message[messageNr], time, result.first, result.second);
+          ProcessHitMessage(message[messageNr], time, std::get<0>(result), std::get<1>(result));
           break;
         }
         case stsxyter::MessType::TsMsb: {
@@ -88,7 +88,7 @@ namespace cbm::algo::much
           break;
         }
         default: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
 
diff --git a/algo/detectors/much/UnpackMS.h b/algo/detectors/much/UnpackMS.h
index 1f9e413f841596f1fc8eb24262a9970d82766af7..c34b9e90b6564675498382d86c9ccf23dad9a6cf 100644
--- a/algo/detectors/much/UnpackMS.h
+++ b/algo/detectors/much/UnpackMS.h
@@ -68,6 +68,14 @@ namespace cbm::algo::much
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
 
   /** @class UnpackMS
    ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de>
@@ -75,7 +83,7 @@ namespace cbm::algo::much
    ** @since 25 November 2021
    ** @brief Unpack algorithm for STS
    **/
-  class UnpackMS : public UnpackMSBase<CbmMuchDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmMuchDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct with parameters **/
diff --git a/algo/detectors/rich/Unpack.h b/algo/detectors/rich/Unpack.h
index ec21c5d84757186dc5693abb7c7d6037f669ac12..93f414f51a925d52a78977ec26b139931350693d 100644
--- a/algo/detectors/rich/Unpack.h
+++ b/algo/detectors/rich/Unpack.h
@@ -13,7 +13,7 @@ namespace cbm::algo::rich
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmRichDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmRichDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/rich/UnpackMS.cxx b/algo/detectors/rich/UnpackMS.cxx
index 07c826e6d023c9f1f0dd3e11850bc302aeb8e37e..c59e211949b6908031f3d15a779f351ea73878ab 100644
--- a/algo/detectors/rich/UnpackMS.cxx
+++ b/algo/detectors/rich/UnpackMS.cxx
@@ -45,7 +45,7 @@ namespace cbm::algo::rich
     [[maybe_unused]] uint32_t msIndexWord1 = reader.NextWord();
     [[maybe_unused]] uint32_t msIndexWord2 = reader.NextWord();
 
-    return std::make_pair(std::move(ctx.digis), std::move(ctx.monitor));
+    return std::make_tuple(std::move(ctx.digis), std::move(ctx.monitor), UnpackAuxData());
   }
 
 
@@ -243,7 +243,7 @@ namespace cbm::algo::rich
       return;
     }
     else {
-      epoch = ProcessEpoch(word);
+      epoch    = ProcessEpoch(word);
       wasEpoch = true;
     }
 
@@ -280,7 +280,7 @@ namespace cbm::algo::rich
             return;
           }
           wasEpoch = true;
-          epoch = ProcessEpoch(word);
+          epoch    = ProcessEpoch(word);
           break;
         }
         case TdcWordType::Header: {
diff --git a/algo/detectors/rich/UnpackMS.h b/algo/detectors/rich/UnpackMS.h
index 0dd092c3019de79a5f8627679b5b7ad4b86ee728..30e66555ab020f55102fd981cfa0637b0e0e5666 100644
--- a/algo/detectors/rich/UnpackMS.h
+++ b/algo/detectors/rich/UnpackMS.h
@@ -105,8 +105,16 @@ namespace cbm::algo::rich
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
 
-  class UnpackMS : public UnpackMSBase<CbmRichDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmRichDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct from parameters **/
diff --git a/algo/detectors/sts/Unpack.cxx b/algo/detectors/sts/Unpack.cxx
index c153322e42866fc4945c004e0097a8d74ef2cacb..e5f7003fe2d66c19b9a6aac89d08c9918a48a63e 100644
--- a/algo/detectors/sts/Unpack.cxx
+++ b/algo/detectors/sts/Unpack.cxx
@@ -14,14 +14,14 @@ Unpack::Unpack(const Config& config) : fConfig(config)
   uint32_t numChansPerAsicSts   = 128;  // R/O channels per ASIC for STS
   uint32_t numAsicsPerModuleSts = 16;   // Number of ASICs per module for STS
 
-  constexpr u8 SystemVersion     = 0x20;
+  constexpr u8 SystemVersion = 0x20;
 
   auto equipIdsSts = fConfig.readout.GetEquipmentIds();
   for (auto& equip : equipIdsSts) {
     sts::UnpackPar par{};
-    par.fNumChansPerAsic    = numChansPerAsicSts;
-    par.fNumAsicsPerModule  = numAsicsPerModuleSts;
-    const size_t numElinks  = fConfig.readout.GetNumElinks(equip);
+    par.fNumChansPerAsic   = numChansPerAsicSts;
+    par.fNumAsicsPerModule = numAsicsPerModuleSts;
+    const size_t numElinks = fConfig.readout.GetNumElinks(equip);
     for (size_t elink = 0; elink < numElinks; elink++) {
       sts::UnpackElinkPar elinkPar;
       auto mapEntry        = fConfig.readout.Map(equip, elink);
diff --git a/algo/detectors/sts/Unpack.h b/algo/detectors/sts/Unpack.h
index 8391e86dc68e397332bfafdc3862d2d5de6d3a72..50e8720861c1d56b4393de6ac08beb98f7ca83b6 100644
--- a/algo/detectors/sts/Unpack.h
+++ b/algo/detectors/sts/Unpack.h
@@ -14,7 +14,7 @@ namespace cbm::algo::sts
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmStsDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmStsDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/sts/UnpackMS.cxx b/algo/detectors/sts/UnpackMS.cxx
index e4caf5b730c079d2619a1ad9e99480368bcd12d8..edb5c1a5634289a80927157a219405efc387db0f 100644
--- a/algo/detectors/sts/UnpackMS.cxx
+++ b/algo/detectors/sts/UnpackMS.cxx
@@ -42,18 +42,18 @@ namespace cbm::algo::sts
     auto msSize = msDescr.size;
     if (msSize % sizeof(stsxyter::Message) != 0) {
       L_(error) << "Invalid microslice size: " << msSize;
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
     const uint32_t numMessages = msSize / sizeof(stsxyter::Message);
     if (numMessages < 2) {
       L_(error) << "Microslice too small: " << numMessages;
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
 
     const u32 maxDigis = numMessages - 2;  // -2 for the TS_MSB and EPOCH messages
-    result.first.reserve(maxDigis);
+    std::get<0>(result).reserve(maxDigis);
 
     // --- Interpret MS content as sequence of SMX messages
     auto message = reinterpret_cast<const stsxyter::Message*>(msContent);
@@ -61,14 +61,14 @@ namespace cbm::algo::sts
     // --- The first message in the MS is expected to be of type EPOCH and can be ignored.
     if (message[0].GetMessType() != stsxyter::MessType::Epoch) {
       L_(error) << "First message in microslice is not of type EPOCH";
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
 
     // --- The second message must be of type ts_msb.
     if (message[1].GetMessType() != stsxyter::MessType::TsMsb) {
       L_(error) << "Second message in microslice is not of type TS_MSB";
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
     ProcessTsmsbMessage(message[1], time);
@@ -80,7 +80,7 @@ namespace cbm::algo::sts
       switch (message[messageNr].GetMessType()) {
 
         case stsxyter::MessType::Hit: {
-          ProcessHitMessage(message[messageNr], time, result.first, result.second);
+          ProcessHitMessage(message[messageNr], time, std::get<0>(result), std::get<1>(result));
           break;
         }
         case stsxyter::MessType::TsMsb: {
@@ -88,7 +88,7 @@ namespace cbm::algo::sts
           break;
         }
         default: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
 
diff --git a/algo/detectors/sts/UnpackMS.h b/algo/detectors/sts/UnpackMS.h
index 33cb29bc0d010e4fc3ef0a700b42a5da8f35c565..b115066d9b97fb932e0309a12d01dc32bd6cb4bb 100644
--- a/algo/detectors/sts/UnpackMS.h
+++ b/algo/detectors/sts/UnpackMS.h
@@ -73,13 +73,22 @@ namespace cbm::algo::sts
     }
   };
 
+  /** @struct UnpackStsAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for STS unpacking
+   **/
+  struct UnpackAuxData {
+    std::vector<bool> fMissedEvent;  ///< Missed event flag for returned digis
+  };
+
   /** @class UnpackMS
    ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de>
    ** @author Volker Friese <v.friese@gsi.de>
    ** @since 25 November 2021
    ** @brief Unpack algorithm for STS
    **/
-  class UnpackMS : public UnpackMSBase<CbmStsDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmStsDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Default constructor **/
diff --git a/algo/detectors/tof/Unpack.h b/algo/detectors/tof/Unpack.h
index 3b49776c291945f34aba2d04bbe5da3968caac43..a78ff079abccd9cff129bc68f27e40617a671afb 100644
--- a/algo/detectors/tof/Unpack.h
+++ b/algo/detectors/tof/Unpack.h
@@ -12,7 +12,7 @@ namespace cbm::algo::tof
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmTofDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmTofDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/tof/UnpackMS.cxx b/algo/detectors/tof/UnpackMS.cxx
index 4294e61c65648e158fa89326ee4fc3140a2360bc..b9cd5dcf017f30054b4e71eeeb7818565d97f3bf 100644
--- a/algo/detectors/tof/UnpackMS.cxx
+++ b/algo/detectors/tof/UnpackMS.cxx
@@ -24,8 +24,8 @@ namespace cbm::algo::tof
   {
 
     // --- Output data
-    Result_t result   = {};
-    TimeSpec time     = {};
+    Result_t result = {};
+    TimeSpec time   = {};
 
     // --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs
     // --- and the epoch is a multiple of ns.
@@ -34,12 +34,12 @@ namespace cbm::algo::tof
     // --- Number of messages in microslice
     auto msSize = msDescr.size;
     if (msSize % sizeof(critof001::Message) != 0) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
     const uint32_t numMessages = msSize / sizeof(critof001::Message);
     if (numMessages < 2) {
-      result.second.fNumErrInvalidMsSize++;
+      std::get<1>(result).fNumErrInvalidMsSize++;
       return result;
     }
 
@@ -47,11 +47,11 @@ namespace cbm::algo::tof
     auto message = reinterpret_cast<const critof001::Message*>(msContent);
 
     const uint32_t maxDigis = numMessages - 2;  // -2 for the TS_MSB and EPOCH messages
-    result.first.reserve(maxDigis);
+    std::get<0>(result).reserve(maxDigis);
 
     // --- The first message in the MS is expected to be of type EPOCH.
     if (message[0].getMessageType() != critof001::MSG_EPOCH) {
-      result.second.fNumErrInvalidFirstMessage++;
+      std::get<1>(result).fNumErrInvalidFirstMessage++;
       return result;
     }
 
@@ -59,14 +59,14 @@ namespace cbm::algo::tof
       const uint64_t msStartEpoch =
         static_cast<uint64_t>(msDescr.idx / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
       if (message[0].getGdpbEpEpochNb() != msStartEpoch) {
-        result.second.fNumErrInvalidStartEpoch++;
+        std::get<1>(result).fNumErrInvalidStartEpoch++;
         return result;
       }
     }
 
     // --- The last message in the MS is expected to be EndOfMs.
     if (!message[numMessages - 1].isEndOfMs()) {
-      result.second.fNumErrInvalidLastMessage++;
+      std::get<1>(result).fNumErrInvalidLastMessage++;
       return result;
     }
     // Check if last message is "EndOfMs"!! Maybe loop to messageNr < numMessages - 1
@@ -78,7 +78,7 @@ namespace cbm::algo::tof
       switch (message[messageNr].getMessageType()) {
 
         case critof001::MSG_HIT: {
-          ProcessHitMessage(message[messageNr], result.first, result.second, time);
+          ProcessHitMessage(message[messageNr], std::get<0>(result), std::get<1>(result), time);
           break;
         }
         case critof001::MSG_EPOCH: {
@@ -86,15 +86,15 @@ namespace cbm::algo::tof
           break;
         }
         case critof001::MSG_SLOWC: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
         case critof001::MSG_SYST: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
         default: {
-          result.second.fNumNonHitOrTsbMessage++;
+          std::get<1>(result).fNumNonHitOrTsbMessage++;
           break;
         }
       }  //? Message type
diff --git a/algo/detectors/tof/UnpackMS.h b/algo/detectors/tof/UnpackMS.h
index c919418c59363ed2b3375105761c26699dd5c534..1a1033cc6bf1d6db7cf2cb6b6efaf9cd1e2eb87d 100644
--- a/algo/detectors/tof/UnpackMS.h
+++ b/algo/detectors/tof/UnpackMS.h
@@ -69,13 +69,22 @@ namespace cbm::algo::tof
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
+
   /** @class UnpackMS
    ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de>
    ** @author Volker Friese <v.friese@gsi.de>
    ** @since 25 November 2021
    ** @brief Unpack algorithm for STS
    **/
-  class UnpackMS : public UnpackMSBase<CbmTofDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmTofDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Default constructor **/
diff --git a/algo/detectors/trd/Unpack.h b/algo/detectors/trd/Unpack.h
index 0791cd2f9cb756d24daf49cba923881f355cdbe4..91dc4d769c8268d6a1f187140fb2cd9883fe0725 100644
--- a/algo/detectors/trd/Unpack.h
+++ b/algo/detectors/trd/Unpack.h
@@ -13,7 +13,7 @@ namespace cbm::algo::trd
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmTrdDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmTrdDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/trd/UnpackMS.cxx b/algo/detectors/trd/UnpackMS.cxx
index d70d8810d7ecb91359b938a6a3599ad0f0f95fc5..40fdd3be35e925dcd9dfbed534b57f2c79558e74 100644
--- a/algo/detectors/trd/UnpackMS.cxx
+++ b/algo/detectors/trd/UnpackMS.cxx
@@ -423,7 +423,7 @@ namespace cbm::algo::trd
 
 
     // Digest the flags from the µSlice
-    digestMsFlags(msDescr.flags, result.second);
+    digestMsFlags(msDescr.flags, std::get<1>(result));
 
     size_t fMsStartTimeRel = (msDescr.idx - tTimeslice);
 
@@ -439,7 +439,7 @@ namespace cbm::algo::trd
       Spadic::NByteContainer<bytes> bCont = bp[iword];
       Spadic::FexWord<sys_ver> fw(bCont);
       if (fw.ht != 0) {
-        result.first.push_back(makeDigi(fw, fMsStartTimeRel));
+        std::get<0>(result).push_back(makeDigi(fw, fMsStartTimeRel));
       }
     }
     return result;
@@ -480,7 +480,7 @@ namespace cbm::algo::trd
     auto criId          = msDescr.eq_id;
 
     // Digest the flags from the µSlice
-    digestMsFlags(msDescr.flags, result.second);
+    digestMsFlags(msDescr.flags, std::get<1>(result));
 
     // Get the number of complete words in the input MS buffer.
     std::uint32_t nwords = mssize / fBytesPerWord;
@@ -488,7 +488,7 @@ namespace cbm::algo::trd
     // We have 32 bit spadic frames in this readout version
     const auto mscontent = reinterpret_cast<const size_t*>(msContent);
 
-    result.first.reserve(nwords);
+    std::get<0>(result).reserve(nwords);
 
     // Loop over all 64bit-Spadic-Words in the current µslice
     for (std::uint32_t istream = 0; istream < fStreamsPerWord; istream++) {
@@ -509,10 +509,10 @@ namespace cbm::algo::trd
 
         switch (kWordtype) {
           case Spadic::MsMessageType::kEPO: {
-            auto tsmsb = getTsMsb(frame, result.second);
+            auto tsmsb = getTsMsb(frame, std::get<1>(result));
             if (((tsmsb - currTsMsb) & 0x3f) == 1 || currTsMsb == -1) ctx.fNrTsMsbVec.at(istream)++;
             currTsMsb = tsmsb;
-            result.second.fNumEpochMsgs++;
+            std::get<1>(result).fNumEpochMsgs++;
             break;
             // FIXME in the kEPO msg we also have further flags that should be extracted
           }
@@ -543,7 +543,7 @@ namespace cbm::algo::trd
               // Ensure that we are on the correct eLink
               elinkId = (frame >> 24) & 0x3f;
               if (elinkId != raw.GetElinkId()) {
-                result.second.fNumElinkMis++;
+                std::get<1>(result).fNumElinkMis++;
               }
 
               // We have 22 adc bits per RDA word lets add them to the buffer...
@@ -571,7 +571,7 @@ namespace cbm::algo::trd
               // Ensure that we are on the correct eLink
               elinkId = (frame >> 24) & 0x3f;
               if (elinkId != raw.GetElinkId()) {
-                result.second.fNumElinkMis++;
+                std::get<1>(result).fNumElinkMis++;
               }
 
               // Number of samples indicator = nsamples % 4
@@ -603,44 +603,44 @@ namespace cbm::algo::trd
                 }
               }
               else {
-                result.second.fNumCorruptEom++;
+                std::get<1>(result).fNumCorruptEom++;
               }
-              result.second.fNumCreatedRawMsgs++;
+              std::get<1>(result).fNumCreatedRawMsgs++;
 
               // the message is done and the raw message container should contain everything we need.
               // So now we can call makeDigi(). Nevertheless there is a chance for a corrupted message,
               // which ends up with 0 samples so we have to check for it.
-              if (isample > 0) result.first.push_back(makeDigi(raw, ctx));
+              if (isample > 0) std::get<0>(result).push_back(makeDigi(raw, ctx));
             }
             else {
               // We move the word counter backwards by one, such that the unexpected message can correctly be digested
               iword--;
-              result.second.fNumMissingEom++;
+              std::get<1>(result).fNumMissingEom++;
             }
             break;
           }
           case Spadic::MsMessageType::kRDA: {
-            result.second.fNumWildRda++;
+            std::get<1>(result).fNumWildRda++;
             break;
           }
           case Spadic::MsMessageType::kEOM: {
-            result.second.fNumWildEom++;
+            std::get<1>(result).fNumWildEom++;
             break;
           }
           case Spadic::MsMessageType::kINF: {
-            result.second.fNumCreatedInfoMsgs++;
+            std::get<1>(result).fNumCreatedInfoMsgs++;
             digestInfoMsg(frame);
             break;
           }
           case Spadic::MsMessageType::kNUL: {
             // last word in Microslice is 0.
             if (iword != (nwords - 1) || (istream != (fStreamsPerWord - 1))) {
-              result.second.fNumWildNul++;
+              std::get<1>(result).fNumWildNul++;
             }
             break;
           }
           case Spadic::MsMessageType::kUNK: {
-            result.second.fNumUnknownWords++;
+            std::get<1>(result).fNumUnknownWords++;
             return result;
             break;
           }
diff --git a/algo/detectors/trd/UnpackMS.h b/algo/detectors/trd/UnpackMS.h
index 59d29bdf2b28721ce43d8bc969e99082a7d60735..35f0d874a50ef214c45d2e245d1c79b8f980171f 100644
--- a/algo/detectors/trd/UnpackMS.h
+++ b/algo/detectors/trd/UnpackMS.h
@@ -92,6 +92,14 @@ namespace cbm::algo::trd
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
 
   /** @class Unpack
    ** @author Dominik Smith <d.smith@gsi.de>
@@ -99,7 +107,7 @@ namespace cbm::algo::trd
    ** @brief Unpack algorithm for TRD
    **/
   template<uint8_t sys_ver>
-  class UnpackMS : public UnpackMSBase<CbmTrdDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmTrdDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct from parameters **/
diff --git a/algo/detectors/trd2d/Unpack.h b/algo/detectors/trd2d/Unpack.h
index 710a90093c83240ba110346f41a179e1dcc23b6d..d2c1f37b9e8eac0bc4955f74fc3717fefb176035 100644
--- a/algo/detectors/trd2d/Unpack.h
+++ b/algo/detectors/trd2d/Unpack.h
@@ -13,7 +13,7 @@ namespace cbm::algo::trd2d
 
   namespace detail
   {
-    using UnpackBase = CommonUnpacker<CbmTrdDigi, UnpackMonitorData>;
+    using UnpackBase = CommonUnpacker<CbmTrdDigi, UnpackMonitorData, UnpackAuxData>;
   }
 
   class Unpack : public detail::UnpackBase {
diff --git a/algo/detectors/trd2d/UnpackMS.cxx b/algo/detectors/trd2d/UnpackMS.cxx
index 4a51f76db15e43117d47d47bd81146116e49d043..714f4c2e81b7066d5beb362fa116ec2bfa46684f 100644
--- a/algo/detectors/trd2d/UnpackMS.cxx
+++ b/algo/detectors/trd2d/UnpackMS.cxx
@@ -92,8 +92,8 @@ namespace cbm::algo::trd2d
       }
       vMess.emplace_back(ch_id, kData, slice, data >> 1, crob_id, lFaspOld);
     }
-    result.first  = FinalizeComponent(ctx);  //TO DO: Original (non-algo) version calls this after MS loop!!
-    result.second = ctx.fMonitor;
+    std::get<0>(result) = FinalizeComponent(ctx);  //TO DO: Original (non-algo) version calls this after MS loop!!
+    std::get<1>(result) = ctx.fMonitor;
 
     return result;
   }
diff --git a/algo/detectors/trd2d/UnpackMS.h b/algo/detectors/trd2d/UnpackMS.h
index 6a280e1a398827e3363e6a488b1fee3cba1a64ce..18a498eecc63f649d81486d9357a3b533bc1bb99 100644
--- a/algo/detectors/trd2d/UnpackMS.h
+++ b/algo/detectors/trd2d/UnpackMS.h
@@ -98,12 +98,21 @@ namespace cbm::algo::trd2d
     }
   };
 
+  /** @struct UnpackAux
+   ** @author Dominik Smith <d.smith@gsi.de>
+   ** @since 24 May 2024
+   ** @brief Auxiliary data for BMON unpacking
+   **/
+  struct UnpackAuxData {
+    ///// TO BE FILLED
+  };
+
   /** @class UnpackMS
    ** @author Dominik Smith <d.smith@gsi.de>
    ** @since 31 January 2023
    ** @brief Unpack algorithm for TRD
    **/
-  class UnpackMS : public UnpackMSBase<CbmTrdDigi, UnpackMonitorData> {
+  class UnpackMS : public UnpackMSBase<CbmTrdDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct from parameters **/
diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx
index 9a09c0f93b4f7a88e8e7964a9fe007971a776425..4288d6df1b4b1f5073beb3942cb864c87a077c3b 100644
--- a/algo/global/Reco.cxx
+++ b/algo/global/Reco.cxx
@@ -409,8 +409,9 @@ auto Reco::RunUnpacker(const std::unique_ptr<Unpacker>& unpacker, const fles::Ti
   if (!unpacker) {
     return {};
   }
-  auto [digis, monitor] = (*unpacker)(ts);
+  auto [digis, monitor, aux] = (*unpacker)(ts);
   QueueUnpackerMetricsDet(monitor);
+  //// TO DO: Send aux somewhere!!
   return digis;
 }
 
diff --git a/algo/unpack/CommonUnpacker.h b/algo/unpack/CommonUnpacker.h
index c76119cdbd6bc93047181c8f7b9e76fe600e664c..76f182dc653da3dd9b01432a2216d6c434d81279 100644
--- a/algo/unpack/CommonUnpacker.h
+++ b/algo/unpack/CommonUnpacker.h
@@ -59,6 +59,11 @@ namespace cbm::algo
     std::vector<MSMonitor> msMonitor;  // monitoring data per microslice
   };
 
+  template<class MSAux>
+  struct UnpackAux {
+    std::vector<MSAux> msAux;  // auxiliary data per microslice
+  };
+
   struct UnpackKey {
     u16 eqId;
     u8 sysVer;
@@ -72,13 +77,14 @@ namespace cbm::algo
     }
   };
 
-  template<class Digi, class MSMonitor>
+  template<class Digi, class MSMonitor, class MSAux>
   class CommonUnpacker {
 
    protected:
     using Monitor_t = UnpackMonitor<MSMonitor>;
-    using Result_t  = std::pair<PODVector<Digi>, Monitor_t>;
-    using Unpack_t  = UnpackMSBase<Digi, MSMonitor>;
+    using Aux_t     = UnpackAux<MSAux>;
+    using Result_t  = std::tuple<PODVector<Digi>, Monitor_t, Aux_t>;
+    using Unpack_t  = UnpackMSBase<Digi, MSMonitor, MSAux>;
 
     std::map<UnpackKey, std::unique_ptr<Unpack_t>> fAlgos;  //< Equipment id to unpacker map. Filled by child class!
 
@@ -91,8 +97,9 @@ namespace cbm::algo
       const size_t numMs = msData.monitor.numMs;
 
       Result_t out;
-      auto& digisOut   = out.first;
-      auto& monitorOut = out.second;
+      auto& digisOut   = std::get<0>(out);
+      auto& monitorOut = std::get<1>(out);
+      auto& auxOut     = std::get<2>(out);
 
       static_cast<detail::UnpackMonitorBase&>(monitorOut) = msData.monitor;
 
@@ -123,8 +130,9 @@ namespace cbm::algo
         }
 
         auto result             = (*algo->second)(msData.msContent[i], msData.msDesc[i], ts.start_time());
-        msDigis[i]              = std::move(result.first);
-        monitorOut.msMonitor[i] = std::move(result.second);
+        msDigis[i]              = std::move(std::get<0>(result));
+        monitorOut.msMonitor[i] = std::move(std::get<1>(result));
+        auxOut.msAux[i]         = std::move(std::get<2>(result));
       }
       xpu::pop_timer();
 
diff --git a/algo/unpack/UnpackMSBase.h b/algo/unpack/UnpackMSBase.h
index d345eb05ef13f0678162724c3169f06c961e0f98..10068e13c64c6e2c0096713bc832b217922b4205 100644
--- a/algo/unpack/UnpackMSBase.h
+++ b/algo/unpack/UnpackMSBase.h
@@ -14,14 +14,15 @@ namespace fles
 namespace cbm::algo
 {
 
-  template<typename D, typename M>
+  template<typename D, typename M, typename A>
   class UnpackMSBase {
 
    public:
     using Digi_t    = D;
     using Monitor_t = M;
+    using Aux_t     = A;
 
-    using Result_t = std::pair<std::vector<Digi_t>, Monitor_t>;
+    using Result_t = std::tuple<std::vector<Digi_t>, Monitor_t, Aux_t>;
 
     virtual ~UnpackMSBase() = default;
 
diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx
index e6a26d5e5a4402e4ef79347239d34ed10fb55cca..b7bcae797a6379c603125dda8accb2de079ccabf 100644
--- a/reco/tasks/CbmTaskUnpack.cxx
+++ b/reco/tasks/CbmTaskUnpack.cxx
@@ -353,7 +353,7 @@ template<class Unpacker>
 auto CbmTaskUnpack::RunUnpacker(const std::unique_ptr<Unpacker>& unpacker, const fles::Timeslice& timeslice,
                                 Monitor& monitor) -> cbm::algo::algo_traits::Output_t<Unpacker>
 {
-  auto [digis, detmon] = (*unpacker)(timeslice);
+  auto [digis, detmon, detaux] = (*unpacker)(timeslice);
   monitor.numCompUsed += detmon.numComponents;
   monitor.numMs += detmon.numMs;
   monitor.numBytes += detmon.sizeBytesIn;