diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go
index cd9d30e113b094c9b77aae0da2661421edef330f..c89bd221efbf503410151c991c87bc825dd393e5 100644
--- a/interfaces/networkManager.go
+++ b/interfaces/networkManager.go
@@ -8,14 +8,12 @@
 package interfaces
 
 import (
-	"github.com/cloudflare/circl/dh/sidh"
+	"encoding/base64"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/client/network/gateway"
 	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/comms/network"
-	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/e2e"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
@@ -38,7 +36,6 @@ type NetworkManager interface {
 
 	CheckGarbledMessages()
 
-
 	// GetAddressSize returns the current address size of IDs. Blocks until an
 	// address size is known.
 	GetAddressSize() uint8
@@ -63,8 +60,6 @@ type NetworkManager interface {
 	SendCMIX(message format.Message, recipient *id.ID, p params.CMIX) (id.Round, ephemeral.Id, error)
 	SendManyCMIX(messages []message.TargetedCmixMessage, p params.CMIX) (id.Round, []ephemeral.Id, error)
 
-
-
 	/* Message Receiving */
 	/* Identities are all network identites which the client is currently
 	trying to pick up message on. Each identity has a default trigger
@@ -94,7 +89,6 @@ type NetworkManager interface {
 	RemoveFingerprints(fingerprints []format.Fingerprint)
 	CheckFingerprint(fingerprint format.Fingerprint) bool
 
-
 	/* trigger - predefined hash based tags appended to all cmix messages
 	which, though trial hashing, are used to determine if a message applies
 	to this client
@@ -157,31 +151,40 @@ type IdentityParams struct {
 	Ephemeral bool
 }
 
+type Preimage []byte
+
+// key returns the key used to identify the Preimage in a map.
+func (pi Preimage) String() string {
+	return base64.StdEncoding.EncodeToString(pi)
+}
+
 type Trigger struct {
-	Preimage []byte
+	Preimage Preimage
 	Type     string
 	Source   []byte
 }
 
 type MessageProcessorFP interface {
-	Process(message format.Message, fingerprint format.Fingerprint)error
+	Process(message format.Message, fingerprint format.Fingerprint)
+	MarkFingerprintUsed(fingerprint format.Fingerprint)
 }
 
 type MessageProcessorTrigger interface {
 	Process(message format.Message, preimage []byte, Type string, source []byte)
+	Equals(trigger MessageProcessorTrigger) bool
 }
 
-type Ratchet interface {
-	SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error)
-	SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error)
-	AddPartner(partnerID *id.ID, partnerPubKey,
-		myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
-		mySIDHPrivKey *sidh.PrivateKey,
-		sendParams, receiveParams params.E2ESessionParams)
-	GetPartner(partnerID *id.ID) (*Manager, error)
-	DeletePartner(partnerId *id.ID)
-	GetAllPartnerIDs() []*id.ID
-}
+//type Ratchet interface {
+//	SendE2E(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error)
+//	SendUnsafe(m message.Send, p params.Unsafe) ([]id.Round, error)
+//	AddPartner(partnerID *id.ID, partnerPubKey,
+//		myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
+//		mySIDHPrivKey *sidh.PrivateKey,
+//		sendParams, receiveParams params.E2ESessionParams)
+//	GetPartner(partnerID *id.ID) (*Manager, error)
+//	DeletePartner(partnerId *id.ID)
+//	GetAllPartnerIDs() []*id.ID
+//}
 
 //for use in key exchange which needs to be callable inside of network
 type SendE2E func(m message.Send, p params.E2E, stop *stoppable.Single) ([]id.Round, e2e.MessageID, time.Time, error)
diff --git a/network/triggers.go b/network/triggers.go
new file mode 100644
index 0000000000000000000000000000000000000000..2e61ee188de4c7ec6cb97f2dd0d6a38165221d64
--- /dev/null
+++ b/network/triggers.go
@@ -0,0 +1,93 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package network
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/interfaces"
+	"sync"
+)
+
+type Triggers struct {
+	triggers map[string][]*Trigger
+	sync.RWMutex
+}
+
+type Trigger struct {
+	interfaces.Trigger
+	interfaces.MessageProcessorTrigger
+}
+
+func NewTriggers() *Triggers {
+	// todo: implement me
+	return nil
+}
+
+func (t *Triggers) Lookup(identityFp,
+	ecrMsgContents []byte) (*Trigger, bool) {
+	t.RLock()
+	defer t.RUnlock()
+
+}
+
+// Add - Adds a trigger which can call a message
+// handing function or be used for notifications.
+// Multiple triggers can be registered for the same preimage.
+//   preimage - the preimage which is triggered on
+//   type - a descriptive string of the trigger. Generally used in notifications
+//   source - a byte buffer of related data. Generally used in notifications.
+//     Example: Sender ID
+func (t *Triggers) Add(trigger interfaces.Trigger,
+	response interfaces.MessageProcessorTrigger) error {
+	t.Lock()
+	defer t.Unlock()
+
+	preimage := trigger.Preimage.String()
+
+	newTrigger := &Trigger{
+		Trigger:                 trigger,
+		MessageProcessorTrigger: response,
+	}
+
+	if existingTriggers, exists := t.triggers[preimage]; exists {
+		t.triggers[preimage] = append(existingTriggers, newTrigger)
+		return nil
+	}
+
+	t.triggers[preimage] = []*Trigger{newTrigger}
+
+	return nil
+}
+
+// RemoveTrigger - If only a single response is associated with the preimage,
+// the entire preimage is removed. If there is more than one response, only
+// the given response is removed. If nil is passed in for response,
+// all triggers for the preimage will be removed.
+func (t *Triggers) RemoveTrigger(preimage interfaces.Preimage,
+	response interfaces.MessageProcessorTrigger) error {
+	t.Lock()
+	defer t.Unlock()
+
+	triggers, exists := t.triggers[preimage.String()]
+	if !exists {
+		return errors.Errorf("No triggers exist with preimage %q", preimage.String())
+	}
+
+	if response == nil {
+		delete(t.triggers, preimage.String())
+		return nil
+	}
+
+	for _, trigger := range triggers {
+		if trigger.Equals(response) {
+			delete(t.triggers, trigger.Preimage.String())
+		}
+	}
+
+	return nil
+}