diff --git a/Reconstruction/eflowRec/src/PFTauFlowElementAssoc.cxx b/Reconstruction/eflowRec/src/PFTauFlowElementAssoc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a8e46cd64853de294dd43c522a74fa478daf416e
--- /dev/null
+++ b/Reconstruction/eflowRec/src/PFTauFlowElementAssoc.cxx
@@ -0,0 +1,151 @@
+/*
+ Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "eflowRec/PFTauFlowElementAssoc.h"
+#include "xAODTau/TauJetContainer.h"
+#include "xAODTau/TauTrack.h"
+#include "xAODPFlow/FlowElementContainer.h"
+#include "xAODPFlow/FlowElement.h"
+
+typedef ElementLink<xAOD::TauJetContainer> TauJetLink_t;
+typedef ElementLink<xAOD::FlowElementContainer> FELink_t;
+
+PFTauFlowElementAssoc::PFTauFlowElementAssoc(const std::string& name,
+              ISvcLocator* pSvcLocator): AthReentrantAlgorithm(name, pSvcLocator)
+{
+  // Declare the decoration keys
+  declareProperty ("TauNeutralFEDecorKey", m_tauNeutralFEWriteDecorKey = "TauJets.neutralFELinks");
+  declareProperty ("TauChargedFEDecorKey", m_tauChargedFEWriteDecorKey = "TauJets.chargedFELinks");
+
+  declareProperty ("NeutralFETauDecorKey", m_neutralFETauWriteDecorKey = "JetETMissNeutralFlowElements.FE_TauLinks");
+  declareProperty ("ChargedFETauDecorKey", m_chargedFETauWriteDecorKey = "JetETMissChargedFlowElements.FE_TauLinks");
+}
+
+PFTauFlowElementAssoc::~PFTauFlowElementAssoc() {}
+
+StatusCode PFTauFlowElementAssoc::initialize() {
+
+  ATH_MSG_DEBUG("Initializing" << name() << "...");
+
+  ATH_CHECK(m_tauNeutralFEWriteDecorKey.initialize());
+  ATH_CHECK(m_tauChargedFEWriteDecorKey.initialize());
+  ATH_CHECK(m_neutralFETauWriteDecorKey.initialize());
+  ATH_CHECK(m_chargedFETauWriteDecorKey.initialize());
+
+  ATH_CHECK(m_tauJetReadHandleKey.initialize());
+  ATH_CHECK(m_neutralFEReadHandleKey.initialize());
+  ATH_CHECK(m_chargedFEReadHandleKey.initialize());
+
+  ATH_MSG_DEBUG("Initialization completed successfully");
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode PFTauFlowElementAssoc::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+/**
+  This algorithm:
+  1) Accesses the relevant FlowElement and TauJet containers
+  2) Loops over the neutral FEs and matches them to the corresponding TauJet clusters, creating the ElementLinks
+     and adding them to the JetETMissNeutralFlowElements container as a decoration
+  3) Loops over the charged FEs and matches them to the corresponding TauJet tracks, creating the ElementLinks
+     and adding them to the JetETMissChargedFlowElements container as a decoration
+  4) Adds the decoration to the TauJet container containing a vector of ElementLinks to corresponding FEs
+**/
+
+StatusCode PFTauFlowElementAssoc::execute(const EventContext &ctx) const {
+
+  // Write decoration handles for linking the TauJet container with the FlowElement container and vice versa
+  SG::WriteDecorHandle< xAOD::TauJetContainer, std::vector<FELink_t> > tauNeutralFEWriteDecorHandle (m_tauNeutralFEWriteDecorKey,ctx);
+  SG::WriteDecorHandle< xAOD::FlowElementContainer, std::vector<TauJetLink_t> > neutralFETauWriteDecorHandle (m_neutralFETauWriteDecorKey,ctx);
+  SG::WriteDecorHandle< xAOD::TauJetContainer, std::vector<FELink_t> > tauChargedFEWriteDecorHandle (m_tauChargedFEWriteDecorKey,ctx);
+  SG::WriteDecorHandle< xAOD::FlowElementContainer, std::vector<TauJetLink_t> > chargedFETauWriteDecorHandle (m_chargedFETauWriteDecorKey,ctx);
+  // Read handles for the TauJet container and the FlowElement container
+  SG::ReadHandle<xAOD::TauJetContainer> tauJetReadHandle (m_tauJetReadHandleKey,ctx);
+  SG::ReadHandle<xAOD::FlowElementContainer> neutralFEReadHandle (m_neutralFEReadHandleKey,ctx);
+  SG::ReadHandle<xAOD::FlowElementContainer> chargedFEReadHandle (m_chargedFEReadHandleKey,ctx);
+
+  // Initialize flow element link containers
+  std::vector<std::vector<FELink_t>> tauNeutralFEVec(tauJetReadHandle->size());
+  std::vector<std::vector<FELink_t>> tauChargedFEVec(tauJetReadHandle->size());
+
+  ////////////////////////////////////////////
+  // Loop over the neutral flow elements
+  ////////////////////////////////////////////
+  for (const xAOD::FlowElement* FE : *neutralFETauWriteDecorHandle) {
+    // Get the index of the flow element cluster
+    size_t FEClusterIndex = FE->otherObjects().at(0)->index();
+
+    std::vector<TauJetLink_t> FETauJetLinks;
+
+    // Loop over the taus
+    for (const xAOD::TauJet* tau : *tauNeutralFEWriteDecorHandle) {
+      // Get the clusters associated to the tau
+      std::vector< ElementLink<xAOD::IParticleContainer> > tauClusters = tau->clusterLinks();
+      for (auto clusLink : tauClusters) {
+        const xAOD::IParticle* clus = *clusLink;
+        // Get the index of the cluster associated to the tau
+        size_t tauClusterIndex = clus->index();
+
+        // Link the tau and the neutral FE if the cluster indices match
+        if (tauClusterIndex == FEClusterIndex) {
+          FETauJetLinks.push_back( TauJetLink_t(*tauJetReadHandle,tau->index()) );
+          tauNeutralFEVec.at(tau->index()).push_back( FELink_t(*neutralFEReadHandle, FE->index()) );
+        }
+
+      } // end tau cluster loop
+    } // end tau loop
+
+    // Add vector of elements links to the tau jets as a decoration to the FE container
+    neutralFETauWriteDecorHandle (*FE) = FETauJetLinks;
+
+  } // end neutral FE loop
+
+  ////////////////////////////////////////////
+  // Loop over the charged flow elements
+  ////////////////////////////////////////////
+  for (const xAOD::FlowElement* FE : *chargedFETauWriteDecorHandle) {
+    // Get the index of the flow element track
+    size_t FETrackIndex = FE->chargedObjects().at(0)->index();
+
+    std::vector<TauJetLink_t> FETauJetLinks;
+
+    // Loop over the taus
+    for (const xAOD::TauJet* tau : *tauChargedFEWriteDecorHandle) {
+      // Get tau tracks associated to the tau
+      std::vector<const xAOD::TauTrack*> tauTracks = tau->tracks(xAOD::TauJetParameters::coreTrack);
+      for (auto tauTrack : tauTracks) {
+        // Get track associated to the tau track to use for matching
+        const xAOD::TrackParticle* tauIDTrack = tauTrack->track();
+        // Get the index of the track associated to the tau
+        size_t tauIDTrackIndex = tauIDTrack->index();
+
+        // Link the tau and the charged FE if the track indices match
+        if (tauIDTrackIndex == FETrackIndex) {
+          FETauJetLinks.push_back( TauJetLink_t(*tauJetReadHandle,tau->index()) );
+          tauChargedFEVec.at(tau->index()).push_back( FELink_t(*chargedFEReadHandle, FE->index()) );
+        }
+      } // end tau track loop
+    } // end tau loop
+
+    // Add vector of elements links to the tau jets as a decoration to the FE container
+    chargedFETauWriteDecorHandle (*FE) = FETauJetLinks;
+
+  } // end charged FE loop
+
+  ////////////////////////////////////////////
+  // Write decorations to TauJet container
+  ////////////////////////////////////////////
+  // Add vectors of Flow Element (FE) Links as decorations to the TauJet container
+  for (const xAOD::TauJet* tau : *tauNeutralFEWriteDecorHandle) {
+    tauNeutralFEWriteDecorHandle (*tau) = tauNeutralFEVec.at(tau->index());
+    tauChargedFEWriteDecorHandle (*tau) = tauChargedFEVec.at(tau->index());
+  }
+
+  ATH_MSG_DEBUG("Execute completed successfully");
+
+  return StatusCode::SUCCESS;
+}