diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/HypoBase.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/HypoBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea4a9b4a284a5c82c493a06c3cc96976ca700e26
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/HypoBase.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef DECISIONHANDLING_HYPOBASE_H
+#define DECISIONHANDLING_HYPOBASE_H 1
+
+#include "DecisionHandling/TrigCompositeUtils.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "StoreGate/ReadHandleKeyArray.h"
+
+class HypoBase : public ::AthReentrantAlgorithm {
+  /**
+   * @class HypoBase
+   * @brief Hypothesis algorithms take the output of reco algorithms and the decision from the preceeding InputMaker, to produce a new decision.
+This is a base class for HLT Hypos to reduce boilerplate and enforce the common naming scheme for decision handle keys. Derived classes will have to add specific reco data read & write keys to suit their purpose.
+   **/
+ public:
+  /// constructor, to be called by sub-class constructors
+  HypoBase( const std::string& name, ISvcLocator* pSvcLocator );
+  /// destructor
+  virtual ~HypoBase(); 
+  /// initialise this base class and renounce input decision key handles
+  StatusCode initialize() override;
+  /// execute to be implemented in derived clas
+  virtual StatusCode execute_r(const EventContext&) const = 0;
+  //StatusCode execute(){};
+  virtual StatusCode finalize() = 0;
+  /// special method for initialisation of derived classes, to be implemented by them, called from base class initialize
+  virtual StatusCode subInitialize()= 0;  
+ protected:
+  /// methods for derived classes to access handles of the base class input and output decisions; other read/write handles may be implemented by derived classes
+  const SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer>& decisionInput() const;
+  const SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer>& decisionOutput() const;
+ private:
+  /// input decisions, will be implicit (renounced).
+  SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer> m_input { this, "previousDecisions", "InputDecision", "Input Decision (implicit)" };
+  /// output decisions
+  SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer> m_output { this, "Output", "OutputDecision", "Ouput Decision" };
+  // for future implementation: ToolHandleArray<ITestHypoTool> m_tools { this, "HypoTools", {}, "Hypo tools" };
+};
+
+
+#endif // DECISIONHANDLING_HYPOBASE_H
diff --git a/Trigger/TrigSteer/DecisionHandling/src/HypoBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/HypoBase.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9a87a5c06d55e779614401b41768ea46125283eb
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/src/HypoBase.cxx
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "DecisionHandling/HypoBase.h"
+
+HypoBase::HypoBase( const std::string& name, ISvcLocator* pSvcLocator )
+  : ::AthReentrantAlgorithm( name, pSvcLocator ) {}
+
+HypoBase::~HypoBase() {} 
+
+const SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer>& HypoBase::decisionInput() const{
+  return m_input;
+}
+
+const SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer>& HypoBase::decisionOutput() const{
+  return m_output;
+}
+
+StatusCode HypoBase::initialize() {
+  CHECK( m_input.initialize() );
+  renounce(m_input); // make inputs implicit, i.e. not required by scheduler
+  ATH_MSG_DEBUG("Will consume implicit decision: " << m_input.key() );
+  CHECK( m_output.initialize() );
+  ATH_MSG_DEBUG(" and produce decision: " << m_output.key() );
+  // initialise sub class
+  CHECK ( subInitialize() );
+  return StatusCode::SUCCESS;
+}
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
index da76a4bd84a26ccf95224b7f0afc4e43316cbaf5..9698e07dee952380dbccfb4378e2410335db9786 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
@@ -19,7 +19,8 @@ StatusCode InputMakerBase::initialize() {
   for (auto& input: m_inputs){  
     ATH_MSG_DEBUG( " "<<input.key() );
   }
-  ATH_MSG_DEBUG(" and produce decisions: " << m_outputs );
+  CHECK( m_outputs.initialize() );
+  ATH_MSG_DEBUG(" and produce decisions: ");
   for (auto& output: m_outputs){  
     ATH_MSG_DEBUG( " "<<output.key() );
   }
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
index b3a4e2d0c9d0b7a6784d50db23967f9b3e5c2ee6..f921efcc95bc697a0ef1728e459f8ba3d2705ecd 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
@@ -5,45 +5,31 @@
 // TrigUpgradeTest includes
 #include "TestHypoAlg.h"
 
-
-
 namespace HLTTest {
   
-  TestHypoAlg::TestHypoAlg( const std::string& name, 
-			    ISvcLocator* pSvcLocator )    :
-    ::AthReentrantAlgorithm( name, pSvcLocator ) {}
-
+  TestHypoAlg::TestHypoAlg( const std::string& name, ISvcLocator* pSvcLocator ) 
+    : ::HypoBase( name, pSvcLocator ) {}
 
   TestHypoAlg::~TestHypoAlg() {}
-
   
-  StatusCode TestHypoAlg::initialize() {
+  StatusCode TestHypoAlg::subInitialize() {
     ATH_MSG_INFO ("Initializing " << name() << "...");
-    CHECK( m_output.initialize() );
     CHECK( m_recoInput.initialize() );
-    CHECK( m_previousDecisions.initialize() );
-    renounce(m_previousDecisions);
-    ATH_MSG_DEBUG("Will consume implicit previous decisions "<< m_previousDecisions.key());
-    //    for (auto& input: m_previousDecisions){  
-    //ATH_MSG_DEBUG(" "<<input.key());
-    //}
     CHECK( m_tools.retrieve() );  
     return StatusCode::SUCCESS;
   }
 
   StatusCode TestHypoAlg::finalize() {
     ATH_MSG_INFO( "Finalizing " << name() << "..." );
-
     return StatusCode::SUCCESS;
   }
 
 
   StatusCode TestHypoAlg::execute_r( const EventContext& context ) const {  
     ATH_MSG_DEBUG( "Executing " << name() << "..." );
-    
-    auto previousDecisionsHandle = SG::makeHandle( m_previousDecisions, context );
+    auto previousDecisionsHandle = SG::makeHandle( decisionInput(), context );
     if( not previousDecisionsHandle.isValid() ) {//implicit
-      ATH_MSG_DEBUG( "No implicit RH for previous decisions "<<  m_previousDecisions.key()<<": is this expected?" );
+      ATH_MSG_DEBUG( "No implicit RH for previous decisions "<<  decisionInput().key()<<": is this expected?" );
       return StatusCode::SUCCESS;      
     }
     
@@ -95,7 +81,7 @@ namespace HLTTest {
 	 auto d = newDecisionIn(decisions.get());
 	 d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>(m_recoInput.key(), counter) );// feature used by the Tool
 	 d->setObjectLink( "initialRoI", featurelink );// this is used by the InputMaker
-	 d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions.key(), pos) );// link to previous decision object
+	 d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(decisionInput().key(), pos) );// link to previous decision object
        }
        else{
 	 ATH_MSG_ERROR( " Can not find reference to previous decision from feature " + m_linkName.value() + " from reco object " << counter );
@@ -112,7 +98,7 @@ namespace HLTTest {
       }
     }
 
-    auto outputHandle = SG::makeHandle(m_output, context);
+    auto outputHandle = SG::makeHandle(decisionOutput(), context);
     CHECK( outputHandle.record(std::move(decisions), std::move(aux) ) );
   
     ATH_MSG_DEBUG( "Exiting with "<< outputHandle->size() <<" decisions");
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.h b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.h
index dd204e13413a75f986133b8345e975f1d7137a1c..637f22e4f60aa2574043f1c49e393f6041119794 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.h
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.h
@@ -6,7 +6,7 @@
 
 
 #include <string>
-#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "DecisionHandling/HypoBase.h"
 #include "xAODTrigger/TrigCompositeContainer.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
 #include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
@@ -20,33 +20,25 @@ namespace HLTTest {
 
   using namespace TrigCompositeUtils;
   
-  class TestHypoAlg : public ::AthReentrantAlgorithm 
+  class TestHypoAlg : public ::HypoBase 
   
   { 
   public: 
     TestHypoAlg( const std::string& name, ISvcLocator* pSvcLocator );
-
     virtual ~TestHypoAlg(); 
 
-
-    StatusCode  initialize() override;
-    virtual StatusCode  execute_r( const EventContext& context ) const override;
-    StatusCode  finalize() override;
-
+    StatusCode subInitialize() override;
+    virtual StatusCode execute_r( const EventContext& context ) const override;
+    StatusCode finalize() override;
 
   private:
     typedef TrigRoiDescriptor FeatureOBJ;
     typedef TrigRoiDescriptorCollection FeatureContainer;
-
+    // the DecisionContainer read/write handle keys are in the base class, called previousDecisions and Output
     TestHypoAlg();
     ToolHandleArray<ITestHypoTool> m_tools                       { this, "HypoTools", {}, "Hypo tools" };
     SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_recoInput  { this, "Input", "Input", "Key for reco input"};
-    
-    SG::ReadHandleKey <DecisionContainer> m_previousDecisions    { this, "previousDecisions", "previousDecisions", "Key for decisions per RoI" };
-    SG::WriteHandleKey<DecisionContainer> m_output               { this, "Output", "Output", "Key for decision output"};
-
     StringProperty m_linkName {this, "LinkName", "initialRoI",  "name of the link to the features in the decision, e.g. 'feature', 'initialRoI'"};
-
    
   };