diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigBlock.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigBlock.py
index 4ebcbfae7ebcac8a609ea0bdf872ab929a32b28d..f9b75e7c8ecf87f9d7f66a8b22025fece0e38aee 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigBlock.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigBlock.py
@@ -10,6 +10,27 @@ class ConfigBlockOption:
         self.noneAction = noneAction
 
 
+
+class ConfigBlockDependency():
+    """Class encoding a blocks dependence on other blocks."""
+
+    def __init__(self, blockName, required=True):
+        self.blockName = blockName
+        self.required = required
+
+
+    def __eq__(self, name):
+        return self.blockName == name
+
+
+    def __str__(self):
+        return self.blockName
+
+
+    def __repr__(self):
+        return f'ConfigBlcokDependency(blockName="{self.blockName}", required={self.required})'
+
+
 class ConfigBlock:
     """the base class for classes implementing individual blocks of
     configuration
@@ -57,8 +78,9 @@ class ConfigBlock:
 
     """
 
-    # groupName is only a placeholder here
     def __init__ (self) :
+        self._blockName = ''
+        self._dependencies = []
         self._options = {}
         # used with block configuration to set arbitrary option
         self.addOption('groupName', '', type=str,
@@ -66,6 +88,36 @@ class ConfigBlock:
                 ' option at an arbitrary location.'))
 
 
+    def setBlockName(self, name):
+        """Set blockName"""
+        self._blockName = name
+
+    def getBlockName(self, name):
+        """Get blockName"""
+        return self._blockName
+
+    def addDependency(self, dependencyName, required=True):
+        """
+        Add a dependency for the block. Dependency is corresponds to the
+        blockName of another block. If requried is True, will throw an
+        error if dependency is not present; otherwise will move this
+        block after the required block. If required is False, will do
+        nothing if required block is not present; otherwise, it will
+        move block after required block.
+        """
+        self._dependencies.append(ConfigBlockDependency(dependencyName, required))
+        # add option to block ignore dependencies
+        self.addOption('ignoreDependencies', [], type=list,
+            info='List of dependencies defined in the ConfigBlock to ignore.')
+
+    def hasDependencies(self):
+        """Return True if there is a dependency."""
+        return bool(self._dependencies)
+
+    def getDependencies(self):
+        """Return the list of dependencies. """
+        return self._dependencies
+
     def addOption (self, name, defaultValue, *, 
             type, info='', noneAction='ignore', required=False) :
         """declare the given option on the configuration block
@@ -127,3 +179,15 @@ class ConfigBlock:
         behavior, interface or be removed/replaced entirely.
         """
         return name in self._options
+
+
+    def __eq__(self, blockName):
+        """
+        Implementation of == operator. Used for seaching configSeque.
+        E.g. if blockName in configSeq:
+        """
+        return self._blockName == blockName
+
+
+    def __str__(self):
+        return self._blockName
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py
index 2b9bdcee4c3faf835ff078f9900f69a4b3dcdf0f..6a7d6969c26db0ab3da26e772ef08587835f8298 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py
@@ -31,14 +31,11 @@ def getDefaultArgs(func):
 
 def getFuncArgs(func):
     """return list of input parameters"""
-    signature = inspect.signature(func)
-    return list(signature.parameters.keys())
-
-
-def getClassArgs(func):
-    """return list of args used i=ton initialize class"""
-    args = list(inspect.signature(func.__init__).parameters.keys())
-    args.remove('self')
+    if isinstance(func, dict):
+        args = list(inspect.signature(func.__init__).parameters.keys())
+        args.remove('self')
+    else:
+        args = list(inspect.signature(func).parameters.keys())
     return args
 
 
@@ -52,7 +49,7 @@ class FactoryBlock():
         self.options = options
         self.defaults = defaults
         if subAlgs is None:
-            self.subAlgs = []
+            self.subAlgs = {}
         else:
             self.subAlgs = subAlgs
 
@@ -121,10 +118,7 @@ class ConfigFactory():
         """Add class to list of available algorithms"""
         if not callable(alg):
             raise ValueError(f"{algName} is not a callable.")
-        if isinstance(alg, type):
-            opts = getClassArgs(alg)
-        else:
-            opts = getFuncArgs(alg)    
+        opts = getFuncArgs(alg)
 
         if superBlocks is None:
             superBlocks = [self.ROOTNAME]
@@ -162,24 +156,25 @@ class ConfigFactory():
                 order.insert(order.index(pos), algName)
             else:
                 raise ValueError(f"{pos} does not exit in already added config blocks")
-
         return
 
 
     def printAlgs(self, printOpts=False):
         """Prints algorithms exposed to configuration"""
-        algs = self._algs
-        for alg, algInfo in algs.items():
-            algName = algInfo.alg.__name__
-            algOptions = algInfo.options
-            algDefaults = algInfo.defaults
-            print(f"{alg} -> {algName}")
-            if printOpts and algOptions:
-                for opt in algOptions:
-                    if algDefaults and opt in algDefaults:
-                        print(f"    {opt}: {algDefaults[opt]}")
-                    else:
-                        print(f"    {opt}")
+        def printAlg(algs):
+            for alg, algInfo in algs.items():
+                algName = algInfo.alg.__name__
+                algOptions = algInfo.options
+                algDefaults = algInfo.defaults
+                print(f"{alg} -> {algName}")
+                if printOpts and algOptions:
+                    for opt in algOptions:
+                        if algDefaults and opt in algDefaults:
+                            print(f"    {opt}: {algDefaults[opt]}")
+                        else:
+                            print(f"    {opt}")
+                printAlg(algInfo.subAlgs)
+        printAlg(self._algs)
         return
 
 
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigSequence.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigSequence.py
index 4216927d847e382b50183d392c6fbbc415bd5aba..583eb1ce927583d83a4dd3c0c0721385d9c0a56f 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigSequence.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigSequence.py
@@ -53,6 +53,51 @@ class ConfigSequence:
         for block in self._blocks:
             block.makeAlgs (config)
 
+    def reorderAlgs(self):
+        """
+        Check for blocks with dependencies.
+
+        If a block requried another block that is not present, will
+        throw an error; Otherwise, will move block immediately after
+        required block. If dependency is not requried, will move
+        after other block, if it is present.
+
+        Note: this implementation can only move blocks forward.
+        """
+        def moveBlock(blocks):
+            for i, block in enumerate(blocks):
+                # the 'ignoreDependencies' option is added with a dep.
+                ignore = block.getOptionValue('ignoreDependencies')
+                if block.hasDependencies():
+                    depIdx = i
+                    for dep in block.getDependencies():
+                        if dep in ignore:
+                            continue
+                        # find dep with largest idx
+                        if dep in blocks:
+                            tmpIdx = blocks.index(dep.blockName)
+                            if tmpIdx > depIdx:
+                                depIdx = tmpIdx
+                        elif dep.required:
+                            raise ValueError(f"{dep} block is required"
+                                f" for {block} but was not found.")
+                    # check to see if block is already infront of deps
+                    if depIdx > i:
+                        print(f"> Moving {block} after {blocks[depIdx]}")
+                        # depIdx > i so after pop, depIdx -= 1 -> depIdx is after dep
+                        blocks.insert(depIdx, blocks.pop(i))
+                        return False
+            # nothing to move
+            return True
+        MAXTRIES = 1000
+        for _ in range(MAXTRIES):
+             if moveBlock(self._blocks):
+                # sorted
+                break
+        else:
+            raise Exception("Could not order blocks based on dependencies"
+                f" in {MAXTRIES} moves.")
+
 
     def fullConfigure (self, config) :
         """do the full configuration on this sequence
@@ -61,6 +106,7 @@ class ConfigSequence:
         contain all the blocks that will be configured, as it will
         perform all configuration steps at once.
         """
+        self.reorderAlgs()
         self.makeAlgs (config)
         config.nextPass ()
         self.makeAlgs (config)
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText.py
index c17ebdcea3b706ed823c0085cd419f8d38373cdf..7b4b383c1fc86809fbf3dc9ecc3df2952eb9da8e 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText.py
@@ -162,32 +162,32 @@ def makeSequence(configPath, dataType, algSeq, geometry=None, autoconfigFromFlag
                  isPhyslite=False, noPhysliteBroken=False, noSystematics=None):
     """
     """
-    print(os.getcwd())
 
     from AnalysisAlgorithmsConfig.ConfigAccumulator import ConfigAccumulator
 
     config = TextConfig(configPath)
 
-    print(">>> Configuration file read in:")
+    print("\n>>> Configuration file read in:")
     config.printConfig()
 
-    print(">>> Default algorithms")
+    print("\n>>> Default algorithms:")
     config.printAlgs(printOpts=True)
 
-    print(">>> Configuring algorithms based on YAML file")
+    print("\n>>> Configuring algorithms based on YAML file:")
     configSeq = config.configure()
 
     # defaults are added to config as algs are configured
-    print(">>> Configuration used:")
+    print("\n>>> Configuration used:")
     config.printConfig()
 
-    print(">>> ConfigBlocks and their configuration")
-    configSeq.printOptions
-
     # compile
     configAccumulator = ConfigAccumulator(algSeq, dataType, isPhyslite=isPhyslite, geometry=geometry, autoconfigFromFlags=autoconfigFromFlags, noSystematics=noSystematics)
     configSeq.fullConfigure(configAccumulator)
 
+    # blocks can be reordered during configSeq.fullConfigure
+    print("\n>>> ConfigBlocks and their configuration:")
+    configSeq.printOptions()
+
     from AnaAlgorithm.DualUseConfig import isAthena, useComponentAccumulator
     if isAthena and useComponentAccumulator:
         return configAccumulator.CA
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
index 5bfb5dafdce5297085617ae454e4e2b085c03915..e2ed28d90d4a8418985783843928fd929afb95b6 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
@@ -997,11 +997,12 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite,
             disable_commands.append('disable el_select_loose.*')
     configSeq.setOptionValue ('.commands', disable_commands)
 
-    configSeq.printOptions()
-
     configAccumulator = ConfigAccumulator (algSeq, dataType, isPhyslite, geometry, autoconfigFromFlags=autoconfigFromFlags, noSystematics=noSystematics)
     configSeq.fullConfigure (configAccumulator)
 
+    # order can change during fullConfigure
+    configSeq.printOptions()
+
     from AnaAlgorithm.DualUseConfig import isAthena, useComponentAccumulator
     if isAthena and useComponentAccumulator:
         return configAccumulator.CA
diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py
index 3e9a0997f1df098b1786f41ab022dafeb95e0c2e..b26bfd5fc6411628e4dcb70758500a585f0a4a7c 100644
--- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py
@@ -142,4 +142,4 @@ class OutputAnalysisConfig (ConfigBlock):
         alg.selectionDecoration =  f'{selectionDecoration},as_char'
         alg.particles = config.readName (containerName)
         alg.preselection = config.getFullSelection (containerName, selectionName)
-        config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix + '_' + selectionName)
\ No newline at end of file
+        config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix + '_' + selectionName)