diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/IKeyWriterTool.h b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/IKeyWriterTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdf00453c23d8a0bf8efae961b2b28239a6a42cb
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/IKeyWriterTool.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGCONFXAOD_IKEYWRITERTOOL_h
+#define TRIGCONFXAOD_IKEYWRITERTOOL_h
+
+#include "GaudiKernel/IAlgTool.h"
+
+class EventContext;
+
+namespace TrigConf {
+
+  /**
+   * @class Tool to read the key triplet from the conditions store and write it to storegate
+   * for use analysis releases. Optionally return the data to the caller.
+   **/
+  class IKeyWriterTool : virtual public IAlgTool { 
+  public: 
+    DeclareInterfaceID( IKeyWriterTool, 1, 0 );
+
+    /**
+     * @brief Write the event's keys to StoreGate. Return the keys to the caller.
+     * @param[in] ctx The event context
+     * @param[out] smk The written SMK
+     * @param[out] l1psk The written L1 prescale key
+     * @param[out] hltpsk The written HLT prescale key
+     **/
+    virtual StatusCode writeKeys(const EventContext& ctx, uint32_t&smk, uint32_t& l1psk, uint32_t& hltpsk) const = 0;
+
+    /**
+     * @brief Version without return values
+     * @param[in] ctx The event context
+     **/
+    virtual StatusCode writeKeys(const EventContext& ctx) const = 0;
+
+  };
+
+}
+
+#endif
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/KeyWriterTool.h b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/KeyWriterTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..322f432bc6f7f4c3e83956277e8bb098c6212034
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/KeyWriterTool.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGCONFXAOD_KEYWRITERTOOL_H 
+#define TRIGCONFXAOD_KEYWRITERTOOL_H
+
+// Interface includes
+#include "IKeyWriterTool.h"
+
+// Framework includes
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "StoreGate/ReadCondHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+
+// Data includes
+#include "TrigConfData/HLTMenu.h"
+#include "TrigConfData/HLTPrescalesSet.h"
+#include "TrigConfData/L1PrescalesSet.h"
+#include "xAODTrigger/TrigConfKeys.h"
+
+
+namespace TrigConf {
+
+  /**
+   * @class Writes trigger keys used when event was processed.
+   * Optionally returns the written keys to the caller
+   **/
+  class KeyWriterTool : public extends<AthAlgTool, IKeyWriterTool> {
+    public:
+
+    KeyWriterTool() = delete;
+
+    KeyWriterTool( const std::string& type, const std::string& name, const IInterface* parent );
+
+    virtual ~KeyWriterTool();
+
+    virtual StatusCode initialize() final;
+
+    virtual StatusCode writeKeys(const EventContext& ctx, uint32_t&smk, uint32_t& l1psk, uint32_t& hltpsk) const final;
+
+    virtual StatusCode writeKeys(const EventContext& ctx) const final;
+
+    private: 
+
+    SG::ReadCondHandleKey<TrigConf::L1PrescalesSet> m_l1PrescaleSetInputKey{ this, "L1Prescales", "L1Prescales", "L1 prescales set key"};
+    SG::ReadCondHandleKey<TrigConf::HLTPrescalesSet> m_hltPrescaleSetInputKey{ this, "HLTPrescales", "HLTPrescales", "HLT prescales set key"};
+    SG::ReadHandleKey<TrigConf::HLTMenu> m_hltMenuInputKey {this, "HLTMenu", "DetectorStore+HLTTriggerMenu", "HLT Menu key"};
+
+    Gaudi::Property<bool> m_includeL1PrescaleKey{this, "IncludeL1PrescaleKey", true, "Set this to false when running this tool online."};
+
+    SG::WriteHandleKey<xAOD::TrigConfKeys> m_writeKeys {this, "ConfKeys", "TrigConfKeys", "SG Key of key triplet object."};
+  };
+
+}
+
+
+#endif 
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/KeyWriterTool.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/src/KeyWriterTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6c8d04215ef242cba92279d3173217bb7db8212c
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/KeyWriterTool.cxx
@@ -0,0 +1,63 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigConfxAOD/KeyWriterTool.h"
+
+#include <limits>
+
+namespace TrigConf {
+
+   KeyWriterTool::KeyWriterTool( const std::string& type, 
+                                 const std::string& name, 
+                                 const IInterface* parent ) :
+      base_class(type, name, parent)
+   {}
+
+   KeyWriterTool::~KeyWriterTool()
+   {}
+
+   StatusCode KeyWriterTool::initialize() {
+      ATH_CHECK( m_l1PrescaleSetInputKey.initialize( m_includeL1PrescaleKey ) );
+      ATH_CHECK( m_hltPrescaleSetInputKey.initialize() );
+      ATH_CHECK( m_hltMenuInputKey.initialize() );
+
+      ATH_CHECK( m_writeKeys.initialize( SG::AllowEmpty ) );
+      return StatusCode::SUCCESS;
+   }
+
+
+   StatusCode KeyWriterTool::writeKeys(const EventContext& ctx) const {
+      uint32_t a, b, c; // Unused
+      return writeKeys(ctx, a, b, c);
+   }
+
+
+   StatusCode KeyWriterTool::writeKeys(const EventContext& ctx, uint32_t&smk, uint32_t& l1psk, uint32_t& hltpsk) const {
+
+      if (m_includeL1PrescaleKey) {
+         SG::ReadCondHandle<TrigConf::L1PrescalesSet> l1psRH(m_l1PrescaleSetInputKey, ctx);
+         ATH_CHECK( l1psRH.isValid() );
+         const TrigConf::L1PrescalesSet* l1PrescaleSet{*l1psRH};
+         l1psk = l1PrescaleSet->psk();
+      } else {
+         l1psk = 0;
+      }
+
+      SG::ReadCondHandle<TrigConf::HLTPrescalesSet> hltpsRH(m_hltPrescaleSetInputKey, ctx);
+      ATH_CHECK( hltpsRH.isValid() );
+      const TrigConf::HLTPrescalesSet* hltPrescaleSet{*hltpsRH};
+      hltpsk = hltPrescaleSet->psk();
+
+      SG::ReadHandle<TrigConf::HLTMenu> hltRH(m_hltMenuInputKey, ctx);
+      ATH_CHECK( hltRH.isValid() );
+      smk = hltRH->smk();
+
+      if (!m_writeKeys.empty()) {
+         SG::WriteHandle<xAOD::TrigConfKeys> writeKeys(m_writeKeys, ctx);
+         ATH_CHECK( writeKeys.record( std::make_unique<xAOD::TrigConfKeys>(smk, l1psk, hltpsk) ) );
+      }
+
+      return StatusCode::SUCCESS;
+   }
+
+}
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/components/TrigConfxAOD_entries.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/src/components/TrigConfxAOD_entries.cxx
index f4c2ec1c3c4511654d0a1b38c318135a09870362..1903a2c23d6f148d11c94b4c92d78adee9b9ba6f 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/components/TrigConfxAOD_entries.cxx
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/components/TrigConfxAOD_entries.cxx
@@ -3,10 +3,12 @@
 #include "../xAODMenuWriterMT.h"
 #include "../xAODMenuReader.h"
 #include "TrigConfxAOD/xAODConfigTool.h"
+#include "TrigConfxAOD/KeyWriterTool.h"
 
 DECLARE_COMPONENT( TrigConf::xAODConfigSvc )
 DECLARE_COMPONENT( TrigConf::xAODMenuWriter )
 DECLARE_COMPONENT( TrigConf::xAODMenuWriterMT )
 DECLARE_COMPONENT( TrigConf::xAODMenuReader )
 DECLARE_COMPONENT( TrigConf::xAODConfigTool )
+DECLARE_COMPONENT( TrigConf::KeyWriterTool )
 
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
index 1845f1253332b7743045ac61555f1c8d2ad8e521..498273ef892d06f69395c42febc0262419e2f145 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
@@ -28,6 +28,7 @@
 // Local include(s):
 #include "xAODMenuWriterMT.h"
 #include "PrintVectorHelper.h"
+#include "TrigConfxAOD/KeyWriterTool.h"
 
 
 namespace TrigConf {
@@ -52,10 +53,14 @@ namespace TrigConf {
       ATH_MSG_VERBOSE( "MetaDataStore = " << m_metaStore );
 
       // Retrieve the necessary service(s):
-      CHECK( m_trigConf.retrieve() );
-      CHECK( m_metaStore.retrieve() );
+      ATH_CHECK( m_trigConf.retrieve() );
+      ATH_CHECK( m_metaStore.retrieve() );
 
-      CHECK( m_eventName.initialize() ); // WriteHandleKey
+      const bool writeKeysWithTool = (m_isHLTJSONConfig && m_isL1JSONConfig);
+      if (writeKeysWithTool) {
+         ATH_CHECK( m_keyWriterTool.retrieve() );
+      }
+      ATH_CHECK( m_eventName.initialize( !writeKeysWithTool ) ); // WriteHandleKey
 
       CHECK( m_HLTMenuKey.initialize(m_isHLTJSONConfig) ); // ReadHandleKey
       CHECK( m_HLTPrescaleSetInputKey.initialize(m_isHLTJSONConfig) ); // ReadCondHandleKey
@@ -140,35 +145,23 @@ namespace TrigConf {
 
    StatusCode xAODMenuWriterMT::execute(const EventContext& ctx) const {
 
-      std::unique_ptr<xAOD::TrigConfKeys> keys;
+      // Create the keys in the "internal format":
+      TrigKey_t ckeys;
+
       if (m_writexAODTriggerMenuJson) {
-         SG::ReadHandle<TrigConf::HLTMenu> hltMenuHandle( m_HLTMenuKey, ctx );
-         SG::ReadCondHandle<TrigConf::L1PrescalesSet> l1PSHandle( m_L1PrescaleSetInputKey, ctx );
-         SG::ReadCondHandle<TrigConf::HLTPrescalesSet> hltPSHandle( m_HLTPrescaleSetInputKey, ctx );
-         ATH_CHECK( hltMenuHandle.isValid() );
-         ATH_CHECK( l1PSHandle.isValid() );
-         ATH_CHECK( hltPSHandle.isValid() );
-         keys = std::make_unique<xAOD::TrigConfKeys>(
-           hltMenuHandle->smk(),
-           l1PSHandle->psk(),
-           hltPSHandle->psk() );
+         // Write to SG via writer tool. 
+         // Get keys back via pass-by-reference
+         ATH_CHECK( m_keyWriterTool->writeKeys(ctx, /*SMK*/ckeys.first, /*L1PSK*/ckeys.second.first, /*HLTPSK*/ckeys.second.second ) );
       } else { // Fall back to R2 TrigConfSvc. Expect this to stop working in the near future (2021+)
-         keys = std::make_unique<xAOD::TrigConfKeys>(
-           m_trigConf->masterKey(),
-           m_trigConf->lvl1PrescaleKey(),
-           m_trigConf->hltPrescaleKey() );
+         ckeys.first = m_trigConf->masterKey();
+         ckeys.second.first = m_trigConf->lvl1PrescaleKey();
+         ckeys.second.second = m_trigConf->hltPrescaleKey();
+         // Write the keys here, do not use the keyWriterTool (this is R3 only)
+         std::unique_ptr<xAOD::TrigConfKeys> keys = std::make_unique<xAOD::TrigConfKeys>(ckeys.first, ckeys.second.first, ckeys.second.second);
+         SG::WriteHandle<xAOD::TrigConfKeys> trigConfKeysWrite(m_eventName, ctx);
+         ATH_CHECK( trigConfKeysWrite.record( std::move(keys) ) );
       }
 
-      // Create the keys in the "internal format":
-      const TrigKey_t ckeys =
-         std::make_pair( keys->smk(),
-            std::make_pair( keys->l1psk(),
-                            keys->hltpsk() ) );
-
-
-      SG::WriteHandle<xAOD::TrigConfKeys> trigConfKeysWrite(m_eventName, ctx);
-      ATH_CHECK( trigConfKeysWrite.record( std::move(keys) ) );
-
       // The following code must only run on one event at a time
       std::lock_guard<std::mutex> lock(m_mutex);
 
@@ -287,7 +280,7 @@ namespace TrigConf {
       // Set its LVL1 information:
       //
       ATH_MSG_DEBUG( "Filling LVL1 information" );
-      SG::ReadHandle<TrigConf::L1Menu> l1MenuHandle = SG::makeHandle( m_L1MenuKey, ctx );
+      SG::ReadHandle<TrigConf::L1Menu> l1MenuHandle( m_L1MenuKey, ctx );
       ATH_CHECK( l1MenuHandle.isValid() );
       const size_t nL1Items = l1MenuHandle->size();
       ATH_MSG_DEBUG("Configuring from " << m_L1MenuKey << " with " << nL1Items << " L1 items");
@@ -336,7 +329,7 @@ namespace TrigConf {
       // Set its HLT information:
       //
       ATH_MSG_DEBUG( "Filling HLT information" );
-      SG::ReadHandle<TrigConf::HLTMenu> hltMenuHandle = SG::makeHandle( m_HLTMenuKey, ctx );
+      SG::ReadHandle<TrigConf::HLTMenu> hltMenuHandle( m_HLTMenuKey, ctx );
       ATH_CHECK( hltMenuHandle.isValid() );
       const size_t nChains = hltMenuHandle->size();
       ATH_MSG_DEBUG("Configuring from " << m_HLTMenuKey << " with " << nChains << " chains");
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
index da884a40524862b1c216330740b4d3e273d6c97c..8ccad8d4f1033bb2a4d8b457e3b615021541edf4 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
@@ -15,6 +15,8 @@ extern "C" {
 #include <set>
 #include <map> // For std::pair...
 
+#include "TrigConfxAOD/IKeyWriterTool.h"
+
 // Gaudi/Athena include(s):
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "GaudiKernel/ServiceHandle.h"
@@ -65,7 +67,7 @@ namespace TrigConf {
       virtual StatusCode execute(const EventContext& ctx) const override;
 
    private:
-      /// 
+ 
       SG::WriteHandleKey<xAOD::TrigConfKeys> m_eventName {this, "EventObjectName", "TrigConfKeys",
         "StoreGate key for the event object"};
 
@@ -118,6 +120,9 @@ namespace TrigConf {
       ServiceHandle< StoreGateSvc > m_metaStore {this, "MetaDataStore", "MetaDataStore",
         "The MetaDataStore"};
 
+      ToolHandle<IKeyWriterTool> m_keyWriterTool{this, "KeyWriterTool", "KeyWriterTool/OfflineKeyWriterTool", 
+          "Writes the keys which are configured when the trigger configuration is written to in-file metadata."};
+
       StatusCode populateL1FromTrigConf(xAOD::TriggerMenu* menu) const;
 
       StatusCode populateHLTFromTrigConf(xAOD::TriggerMenu* menu) const;
diff --git a/Trigger/TrigSteer/L1Decoder/CMakeLists.txt b/Trigger/TrigSteer/L1Decoder/CMakeLists.txt
index d9064e892baabdc7094b6abfbffaa2d8c388eb13..6c516ca73e62d1f7767873b4ac9caeb795de490d 100644
--- a/Trigger/TrigSteer/L1Decoder/CMakeLists.txt
+++ b/Trigger/TrigSteer/L1Decoder/CMakeLists.txt
@@ -17,7 +17,7 @@ atlas_add_library( L1DecoderLib
 atlas_add_component( L1Decoder
                      src/*.cxx src/components/*.cxx L1DecoderRoot/*.cxx
                      INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${CLHEP_LIBRARIES} AthViews AthenaBaseComps AthenaKernel AthenaMonitoringKernelLib GaudiKernel L1DecoderLib StoreGateLib TrigCompositeUtilsLib TrigConfData TrigConfHLTData TrigConfL1Data TrigCostMonitorMTLib TrigSteeringEvent TrigT1Interfaces TrigT1Result TrigTimeAlgsLib xAODEventInfo xAODTrigger )
+                     LINK_LIBRARIES ${CLHEP_LIBRARIES} AthViews AthenaBaseComps AthenaKernel AthenaMonitoringKernelLib GaudiKernel L1DecoderLib StoreGateLib TrigCompositeUtilsLib TrigConfData TrigConfHLTData TrigConfL1Data TrigCostMonitorMTLib TrigSteeringEvent TrigT1Interfaces TrigT1Result TrigTimeAlgsLib xAODEventInfo xAODTrigger TrigConfxAODLib  )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
diff --git a/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py b/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
index 81428a4e5ab671ce0368cc0e964d63a74a83d800..72d702e36405e26f18b9b89200c71158fd23495b 100644
--- a/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
+++ b/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
@@ -94,6 +94,11 @@ def createPrescalingTool():
     prescaler = CompFactory.PrescalingTool(MonTool = PrescalingMonitoring())
     return prescaler
 
+def createKeyWriterTool():
+    keyWriter = CompFactory.getComp('TrigConf::KeyWriterTool')('KeyWriterToolOnline')
+    keyWriter.ConfKeys = 'TrigConfKeysOnline'
+    keyWriter.IncludeL1PrescaleKey = False
+    return keyWriter
 
 def getL1TriggerResultMaker():
     l1trMaker = CompFactory.L1TriggerResultMaker()
@@ -136,6 +141,7 @@ class L1Decoder(CompFactory.L1Decoder) :
             self.roiUnpackers += unpackers
 
         self.prescaler = createPrescalingTool()
+        self.KeyWriterTool = createKeyWriterTool()
 
         from AthenaConfiguration.AllConfigFlags import ConfigFlags as flags
         self.DoCostMonitoring = flags.Trigger.CostMonitoring.doCostMonitoring
@@ -180,6 +186,7 @@ def L1DecoderCfg(flags, seqName = None):
         decoderAlg.roiUnpackers += unpackers
 
     decoderAlg.prescaler = createPrescalingTool()
+    decoderAlg.KeyWriterTool = createKeyWriterTool()
     decoderAlg.DoCostMonitoring = flags.Trigger.CostMonitoring.doCostMonitoring
     decoderAlg.CostMonitoringChain = flags.Trigger.CostMonitoring.chain
 
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
index 715df4d3eee4ae24f36ebea14185405a44cf5609..a4054134a8a9b1fca98a67a46aee8d82c8738eb2 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
@@ -7,6 +7,7 @@
 #include "xAODTrigger/TrigCompositeAuxContainer.h"
 #include "TrigConfHLTData/HLTUtils.h"
 #include "TrigCompositeUtils/TrigCompositeUtils.h"
+#include "TrigConfxAOD/KeyWriterTool.h"
 #include "L1Decoder.h"
 
 L1Decoder::L1Decoder(const std::string& name, ISvcLocator* pSvcLocator)
@@ -31,6 +32,10 @@ StatusCode L1Decoder::initialize() {
   ATH_CHECK( m_roiUnpackers.retrieve() );
   ATH_CHECK( m_prescaler.retrieve() );
 
+  if ( !m_keyWriterTool.empty() ) {
+    ATH_CHECK( m_keyWriterTool.retrieve() );
+  }
+
   ServiceHandle<IIncidentSvc> incidentSvc("IncidentSvc", "CTPSimulation");
   ATH_CHECK(incidentSvc.retrieve());
   incidentSvc->addListener(this,"BeginRun", 200);
@@ -139,6 +144,10 @@ StatusCode L1Decoder::execute (const EventContext& ctx) const {
     ATH_CHECK( unpacker->unpack( ctx, *roib, activeChainSet ) );
   }
 
+  if ( !m_keyWriterTool.empty() ) {
+    ATH_CHECK( m_keyWriterTool->writeKeys(ctx) );
+  }
+
   return StatusCode::SUCCESS;  
 }
 
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
index 195dc6a2bbb51b74cd6b7b60ad3b5e006e697840..bd399dc1b0a3b0fd50478085b11dc52cc5d4d73d 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
@@ -17,6 +17,7 @@
 #include "IRoIsUnpackingTool.h"
 #include "IPrescalingTool.h"
 #include "TrigCostMonitorMT/ITrigCostMTSvc.h"
+#include "TrigConfxAOD/IKeyWriterTool.h"
 
 /*
   @brief an algorithm used to unpack the RoIB result and provide CTP bits, active chains and RoIs
@@ -78,6 +79,9 @@ private:
   ToolHandle<IPrescalingTool> m_prescaler{this, "prescaler", "PrescalingTool/PrescalingTool", 
       "Prescaling tool"};
 
+  ToolHandle<TrigConf::IKeyWriterTool> m_keyWriterTool{this, "KeyWriterTool", "", 
+      "Writes the keys used when the trigger executes on an event"}; 
+
 };
 
 #endif
diff --git a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
index c8cdcce1afefb78b953450b92c563f34affb6eab..f49035203bcb110d0c94d1457002ca6834e4f265 100644
--- a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
+++ b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
@@ -83,6 +83,7 @@ TriggerHLTListRun3 = [
     ('xAOD::TrigDecision#xTrigDecision' ,                    'ESD AODFULL AODSLIM', 'Steer'),
     ('xAOD::TrigDecisionAuxInfo#xTrigDecisionAux.',          'ESD AODFULL AODSLIM', 'Steer'),
     ('xAOD::TrigConfKeys#TrigConfKeys' ,                     'ESD AODFULL AODSLIM', 'Steer'),
+    ('xAOD::TrigConfKeys#TrigConfKeysOnline' ,               'BS ESD AODFULL AODSLIM', 'Steer'),
 
     ('TrigRoiDescriptorCollection#HLT_EMRoIs',                   'BS ESD AODFULL AODSLIM',  'Steer'),
     ('TrigRoiDescriptorCollection#HLT_MURoIs',                   'BS ESD AODFULL AODSLIM',  'Steer'),
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
index c155443ff3206cf13ac27cf1138b0e98cb62c9ac..066e6eaa34fb56551845d82bf44ba4692224e543 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
@@ -427,6 +427,7 @@ def triggerPOOLOutputCfg(flags, edmSet):
     menuwriter = CompFactory.getComp("TrigConf::xAODMenuWriterMT")()
     menuwriter.IsHLTJSONConfig = True
     menuwriter.IsL1JSONConfig = True
+    menuwriter.KeyWriterTool = CompFactory.getComp('TrigConf::KeyWriterTool')('KeyWriterToolOffline')
     acc.addEventAlgo( menuwriter )
 
     # Schedule the insertion of L1 prescales into the conditions store
@@ -440,7 +441,7 @@ def triggerPOOLOutputCfg(flags, edmSet):
     # Ensure OutputStream runs after TrigDecisionMakerMT and xAODMenuWriterMT
     streamAlg.ExtraInputs += [
         ("xAOD::TrigDecision", decmaker.TrigDecisionKey),
-        ("xAOD::TrigConfKeys", menuwriter.EventObjectName)]
+        ("xAOD::TrigConfKeys", menuwriter.KeyWriterTool.ConfKeys)]
 
     # Produce xAOD L1 RoIs from RoIBResult
     from AnalysisTriggerAlgs.AnalysisTriggerAlgsCAConfig import RoIBResultToxAODCfg
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigGetter.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigGetter.py
index 68da693a0298bbd187e4fed827a7df5ab16c2a5b..cee4fcad8cd393da80d0381158fe02c0e4f49722 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigGetter.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigGetter.py
@@ -443,15 +443,15 @@ class TriggerConfigGetter(Configured):
                 from TrigConfxAOD.TrigConfxAODConf import TrigConf__xAODMenuWriter
                 topAlgs += TrigConf__xAODMenuWriter( OverwriteEventObj = True )
             else:
-                from TrigConfxAOD.TrigConfxAODConf import TrigConf__xAODMenuWriterMT
+                from TrigConfxAOD.TrigConfxAODConf import TrigConf__xAODMenuWriterMT, TrigConf__KeyWriterTool
                 menuwriter = TrigConf__xAODMenuWriterMT()
                 menuwriter.IsHLTJSONConfig = True
                 menuwriter.IsL1JSONConfig = True
                 menuwriter.WritexAODTriggerMenu = True # This should be removed in the future
                 menuwriter.WritexAODTriggerMenuJson = True
+                menuwriter.KeyWriterTool = TrigConf__KeyWriterTool('KeyWriterToolOffline')
                 writeTriggerMenu = menuwriter.WritexAODTriggerMenu
                 writeMenuJSON = menuwriter.WritexAODTriggerMenuJson
-
                 topAlgs += menuwriter
 
             # Set up the metadata for the output ESD and AOD: