diff --git a/replication.services.yml b/replication.services.yml
index 6b7941b..cf4c31b 100644
--- a/replication.services.yml
+++ b/replication.services.yml
@@ -3,10 +3,15 @@ services:
     class: Drupal\replication\ProcessFileAttachment
     arguments: ['@current_user', '@entity_type.manager', '@multiversion.entity_index.factory']
 
+#Managers
+  plugin.manager.replication_filter:
+    class: Drupal\replication\Plugin\ReplicationFilterManager
+    parent: default_plugin_manager
+
 #Factories
   replication.changes_factory:
     class: Drupal\replication\ChangesFactory
-    arguments: ['@multiversion.entity_index.sequence', '@entity.manager', '@serializer']
+    arguments: ['@multiversion.entity_index.sequence', '@entity.manager', '@serializer', '@plugin.manager.replication_filter']
   replication.revisiondiff_factory:
     class: Drupal\replication\RevisionDiffFactory
     arguments: ['@multiversion.entity_index.rev']
@@ -94,4 +99,4 @@ services:
   replication.normalizer.comment_item:
     class: Drupal\replication\Normalizer\CommentItemNormalizer
     tags:
-      - { name: normalizer, priority: 10 }
\ No newline at end of file
+      - { name: normalizer, priority: 10 }
diff --git a/src/Annotation/ReplicationFilter.php b/src/Annotation/ReplicationFilter.php
new file mode 100644
index 0000000..047dc67
--- /dev/null
+++ b/src/Annotation/ReplicationFilter.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\replication\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a ReplicationFilter annotation object.
+ *
+ * Plugin Namespace: Plugin\ReplicationFilter
+ *
+ * For a working example, see
+ * \Drupal\replication\Plugin\ReplicationFilter\PublishedFilter
+ *
+ * @see \Drupal\replication\Plugin\ReplicationFilterInterface
+ * @see \Drupal\replication\Plugin\ReplicationFilterManager
+ * @see plugin_api
+ *
+ * @Annotation
+ */
+class ReplicationFilter extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The human-readable name of the ReplicationFilter plugin.
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   *
+   * @ingroup plugin_translatable
+   */
+  public $label;
+
+  /**
+   * A short description of the ReplicationFilter plugin.
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   *
+   * @ingroup plugin_translatable
+   */
+  public $description;
+
+}
diff --git a/src/Changes/Changes.php b/src/Changes/Changes.php
index 1a0f643..ba9517e 100644
--- a/src/Changes/Changes.php
+++ b/src/Changes/Changes.php
@@ -1,27 +1,25 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\replication\Changes\Changes.
- */
-
 namespace Drupal\replication\Changes;
 
+use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\multiversion\Entity\Index\SequenceIndexInterface;
 use Drupal\multiversion\Entity\WorkspaceInterface;
+use Drupal\replication\Plugin\ReplicationFilterManagerInterface;
+// @todo where is the ParameterBagInterface???
+use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\Serializer\SerializerInterface;
-use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 
 /**
- * @todo {@link https://www.drupal.org/node/2282295 Implement remaining feed
- *   query types.}
+ * {@inheritdoc}
  */
 class Changes implements ChangesInterface {
   use DependencySerializationTrait;
 
   /**
    * @var string
+   *   The workspace to generate the changeset from.
    */
   protected $workspaceId;
 
@@ -36,12 +34,31 @@ class Changes implements ChangesInterface {
   protected $serializer;
 
   /**
+   * @var \Drupal\replication\Plugin\ReplicationFilterManagerInterface
+   */
+  protected $filterManager;
+
+  /**
+   * @var string
+   *   The id of the filter plugin to use during replication.
+   */
+  protected $filterName;
+
+  /**
+   * @var ParameterBag
+   *   The parameters passed to the filter function.
+   */
+  protected $parameters;
+
+  /**
    * @var boolean
+   *   Whether to include entities in the changeset.
    */
   protected $includeDocs = FALSE;
 
   /**
    * @var int
+   *   The sequence ID to start including changes from. Result includes $lastSeq.
    */
   protected $lastSeq = 0;
 
@@ -50,12 +67,30 @@ class Changes implements ChangesInterface {
    * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
    * @param \Symfony\Component\Serializer\SerializerInterface $serializer
+   * @param \Drupal\replication\Plugin\ReplicationFilterManagerInterface $filter_manager
    */
-  public function __construct(SequenceIndexInterface $sequence_index, WorkspaceInterface $workspace, EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer) {
+  public function __construct(SequenceIndexInterface $sequence_index, WorkspaceInterface $workspace, EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer, ReplicationFilterManagerInterface $filter_manager) {
     $this->sequenceIndex = $sequence_index;
     $this->workspaceId = $workspace->id();
     $this->entityTypeManager = $entity_type_manager;
     $this->serializer = $serializer;
+    $this->filterManager = $filter_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function filter($filter_name) {
+    $this->filterName = $filter_name;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function parameters(ParameterBag $parameters) {
+    $this->parameters = $parameters;
+    return $this;
   }
 
   /**
@@ -63,6 +98,7 @@ class Changes implements ChangesInterface {
    */
   public function includeDocs($include_docs) {
     $this->includeDocs = $include_docs;
+    return $this;
   }
 
   /**
@@ -81,6 +117,18 @@ class Changes implements ChangesInterface {
       ->useWorkspace($this->workspaceId)
       ->getRange($this->lastSeq, NULL);
 
+    // Setup filter plugin.
+    $parameters = ($this->parameters instanceof ParameterBag) ? $this->parameters : new ParameterBag();
+    $filter = NULL;
+    if (is_string($this->filterName) && $this->filterName) {
+      $filter = $this->filterManager->createInstance($this->filterName);
+    }
+    // If UUIDs are sent as a parameter, but no filter is set, automatically
+    // select the "uuid" filter.
+    elseif ($parameters->has('uuids')) {
+      $filter = $this->filterManager->createInstance('uuid');
+    }
+
     // Format the result array.
     $changes = array();
     foreach ($sequences as $sequence) {
@@ -88,6 +136,20 @@ class Changes implements ChangesInterface {
         continue;
       }
 
+      // Get the document.
+      $revision = NULL;
+      if ($this->includeDocs == TRUE || $filter !== NULL) {
+        /** @var \Drupal\multiversion\Entity\Storage\ContentEntityStorageInterface $storage */
+        $storage = $this->entityTypeManager->getStorage($sequence['entity_type_id']);
+        $storage->useWorkspace($this->workspaceId);
+        $revision = $storage->loadRevision($sequence['revision_id']);
+      }
+
+      // Filter the document.
+      if ($filter !== NULL && !$filter->filter($revision, $parameters)) {
+        continue;
+      }
+
       $uuid = $sequence['entity_uuid'];
       $changes[$uuid] = array(
         'changes' => array(
@@ -99,10 +161,9 @@ class Changes implements ChangesInterface {
       if ($sequence['deleted']) {
         $changes[$uuid]['deleted'] = TRUE;
       }
+
+      // Include the document.
       if ($this->includeDocs == TRUE) {
-        /** @var \Drupal\multiversion\Entity\Storage\ContentEntityStorageInterface $storage */
-        $storage = $this->entityTypeManager->getStorage($sequence['entity_type_id']);
-        $revision = $storage->loadRevision($sequence['revision_id']);
         $changes[$uuid]['doc'] = $this->serializer->normalize($revision);
       }
     }
diff --git a/src/Changes/ChangesInterface.php b/src/Changes/ChangesInterface.php
index 52b4a06..d964e04 100644
--- a/src/Changes/ChangesInterface.php
+++ b/src/Changes/ChangesInterface.php
@@ -1,21 +1,50 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\replication\Changes\ChangesInterface.
- */
-
 namespace Drupal\replication\Changes;
 
-use Drupal\multiversion\Entity\Index\SequenceIndexInterface;
-use Drupal\multiversion\Entity\WorkspaceInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\ParameterBag;
 
+/**
+ * Define and build a changeset for a Workspace.
+ *
+ * @todo {@link https://www.drupal.org/node/2282295 Implement remaining feed
+ *   query types.}
+ * @todo break this class into a value object and a service object: one that
+ * defines the parameters for getting the changeset and the other for executing
+ * the code to build the changeset
+ */
 interface ChangesInterface {
 
   /**
-   * @param boolean $include_docs
+   * Set the id of the filter plugin to use to refine the changeset.
+   *
+   * @param string $filter_name
+   *   The plugin id of a Drupal\replication\Plugin\ReplicationFilterInterface.
+   *
+   * @return \Drupal\replication\Changes\ChangesInterface
+   *   Returns $this.
+   */
+  public function filter($filter_name);
+
+  /**
+   * Set the parameters for the filter plugin.
+   *
+   * @param ParameterBag $parameters
+   *   The parameters passed to the filter function.
+   *
+   * @return \Drupal\replication\Changes\ChangesInterface
+   *   Returns $this.
+   */
+  public function parameters(ParameterBag $parameters);
+
+  /**
+   * Set the flag for including entities in the changeset.
+   *
+   * @param bool $include_docs
+   *   Whether to include entities in the changeset.
+   *
    * @return \Drupal\replication\Changes\ChangesInterface
+   *   Returns $this.
    */
   public function includeDocs($include_docs);
 
@@ -23,7 +52,10 @@ interface ChangesInterface {
    * Sets from what sequence number to check for changes.
    *
    * @param int $seq
+   *   The sequence ID to start including changes from. Result includes $seq.
+   *
    * @return \Drupal\replication\Changes\ChangesInterface
+   *   Returns $this.
    */
   public function lastSeq($seq);
 
diff --git a/src/ChangesFactory.php b/src/ChangesFactory.php
index 5acbcc3..1ab0229 100644
--- a/src/ChangesFactory.php
+++ b/src/ChangesFactory.php
@@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\multiversion\Entity\Index\SequenceIndexInterface;
 use Drupal\multiversion\Entity\WorkspaceInterface;
 use Drupal\replication\Changes\Changes;
+use Drupal\replication\Plugin\ReplicationFilterManagerInterface;
 use Symfony\Component\Serializer\SerializerInterface;
 
 class ChangesFactory implements ChangesFactoryInterface {
@@ -26,6 +27,11 @@ class ChangesFactory implements ChangesFactoryInterface {
   protected $serializer;
 
   /**
+   * @var \Drupal\replication\Plugin\ReplicationFilterManagerInterface
+   */
+  protected $filterManager;
+
+  /**
    * @var \Drupal\replication\Changes\Changes[]
    */
   protected $instances = [];
@@ -34,11 +40,13 @@ class ChangesFactory implements ChangesFactoryInterface {
    * @param \Drupal\multiversion\Entity\Index\SequenceIndexInterface $sequence_index
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
    * @param \Symfony\Component\Serializer\SerializerInterface $serializer
+   * @param \Drupal\replication\Plugin\ReplicationFilterManagerInterface $filter_manager
    */
-  public function __construct(SequenceIndexInterface $sequence_index, EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer) {
+  public function __construct(SequenceIndexInterface $sequence_index, EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer, ReplicationFilterManagerInterface $filter_manager) {
     $this->sequenceIndex = $sequence_index;
     $this->entityTypeManager = $entity_type_manager;
     $this->serializer = $serializer;
+    $this->filterManager = $filter_manager;
   }
 
   /**
@@ -50,7 +58,8 @@ class ChangesFactory implements ChangesFactoryInterface {
         $this->sequenceIndex,
         $workspace,
         $this->entityTypeManager,
-        $this->serializer
+        $this->serializer,
+        $this->filterManager
       );
     }
     return $this->instances[$workspace->id()];
diff --git a/src/Plugin/ReplicationFilter/EntityTypeFilter.php b/src/Plugin/ReplicationFilter/EntityTypeFilter.php
new file mode 100644
index 0000000..5ab7393
--- /dev/null
+++ b/src/Plugin/ReplicationFilter/EntityTypeFilter.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\replication\Plugin\ReplicationFilter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\replication\Plugin\ReplicationFilter\ReplicationFilterBase;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Provides a filter based on entity type.
+ *
+ * Supported parameters:
+ *   entity_type: a comma delimited list of entity type id's to include
+ *
+ * @ReplicationFilter(
+ *   id = "entity_type",
+ *   label = @Translation("Filter By Entity Type"),
+ *   description = @Translation("Replicate only entities that match a given type.")
+ * )
+ */
+class EntityTypeFilter extends ReplicationFilterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function filter(EntityInterface $entity, ParameterBag $parameters) {
+    if ($parameters->has('entity_type')) {
+      $types = $parameters->get('entity_type');
+    }
+    else {
+      $types = '';
+    }
+    $types = explode(',', $types);
+    $types = array_filter(array_map('trim', $types));
+    return in_array($entity->bundle(), $types);
+  }
+
+}
diff --git a/src/Plugin/ReplicationFilter/PublishedFilter.php b/src/Plugin/ReplicationFilter/PublishedFilter.php
new file mode 100644
index 0000000..d103c7c
--- /dev/null
+++ b/src/Plugin/ReplicationFilter/PublishedFilter.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\replication\Plugin\ReplicationFilter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\node\NodeInterface;
+use Drupal\replication\Plugin\ReplicationFilter\ReplicationFilterBase;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Provides a filter for published entities.
+ *
+ * Note: this filter will only work with NodeTypes.
+ *
+ * @ReplicationFilter(
+ *   id = "published",
+ *   label = @Translation("Filter Published Nodes"),
+ *   description = @Translation("Replicate only nodes that are published.")
+ * )
+ */
+class PublishedFilter extends ReplicationFilterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function filter(EntityInterface $entity, ParameterBag $parameters) {
+    if (!$entity instanceof NodeInterface) {
+      return false;
+    }
+    return $entity->isPublished();
+  }
+
+}
diff --git a/src/Plugin/ReplicationFilter/ReplicationFilterBase.php b/src/Plugin/ReplicationFilter/ReplicationFilterBase.php
new file mode 100644
index 0000000..4fa7b92
--- /dev/null
+++ b/src/Plugin/ReplicationFilter/ReplicationFilterBase.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\replication\Plugin\ReplicationFilter;
+
+use Drupal\Core\Plugin\PluginBase;
+use Drupal\replication\Plugin\ReplicationFilterInterface;
+
+/**
+ * Provides a base class for replication filters.
+ *
+ * Having a base class provides a central point to change the behavior of
+ * replication filters, such as adding contexts.
+ */
+abstract class ReplicationFilterBase extends PluginBase implements ReplicationFilterInterface {
+
+  /**
+   * @var string
+   */
+  protected $label;
+
+  /**
+   * @var string
+   */
+  protected $description;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLabel() {
+    return $this->label;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->description;
+  }
+
+}
diff --git a/src/Plugin/ReplicationFilter/UuidFilter.php b/src/Plugin/ReplicationFilter/UuidFilter.php
new file mode 100644
index 0000000..61fdfa0
--- /dev/null
+++ b/src/Plugin/ReplicationFilter/UuidFilter.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\replication\Plugin\ReplicationFilter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\replication\Plugin\ReplicationFilter\ReplicationFilterBase;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Provides filtering by UUID.
+ *
+ * Note: if the entity a UUID refers to references another entity, that
+ * referenced entity's UUID must also be included in order to maintain data
+ * integrity.
+ *
+ * @ReplicationFilter(
+ *   id = "uuid",
+ *   label = @Translation("Filter UUIDs"),
+ *   description = @Translation("Replicate only entities in the set of UUIDs.")
+ * )
+ */
+class UuidFilter extends ReplicationFilterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function filter(EntityInterface $entity, ParameterBag $parameters) {
+    $uuids = $parameters->get('uuids') ?: '';
+    $uuids = explode(',', $uuids);
+    $uuids = array_map('trim', $uuids);
+    return in_array($entity->uuid(), $uuids);
+  }
+
+}
diff --git a/src/Plugin/ReplicationFilterInterface.php b/src/Plugin/ReplicationFilterInterface.php
new file mode 100644
index 0000000..dae6556
--- /dev/null
+++ b/src/Plugin/ReplicationFilterInterface.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\replication\Plugin;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Defines a replication filter.
+ *
+ * Replication filters are used to filter out entities from a changeset during
+ * replication.
+ */
+interface ReplicationFilterInterface extends PluginInspectionInterface {
+
+  /**
+   * Get the label for the filter.
+   *
+   * @return string
+   */
+  public function getLabel();
+
+  /**
+   * Get the description of what the filter does.
+   *
+   * @return string
+   */
+  public function getDescription();
+
+  /**
+   * Filter the given entity.
+   *
+   * @param EntityInterface $entity
+   *   The entity to filter.
+   * @param ParameterBag $parameters
+   *   The parameters passed to the filter function.
+   *
+   * @return bool
+   *   Return TRUE if it should be included, else FALSE.
+   */
+  public function filter(EntityInterface $entity, ParameterBag $parameters);
+
+}
diff --git a/src/Plugin/ReplicationFilterManager.php b/src/Plugin/ReplicationFilterManager.php
new file mode 100644
index 0000000..9fd4abc
--- /dev/null
+++ b/src/Plugin/ReplicationFilterManager.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Drupal\replication\Plugin;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\DefaultPluginManager;
+use Drupal\replication\Plugin\ReplicationFilterManagerInterface;
+
+/**
+ * {@inheritdoc}
+ */
+class ReplicationFilterManager extends DefaultPluginManager implements ReplicationFilterManagerInterface {
+
+  /**
+   * Constructs a ReplicationFilterManager object.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke the alter hook with.
+   */
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+    parent::__construct('Plugin/ReplicationFilter', $namespaces, $module_handler, 'Drupal\replication\Plugin\ReplicationFilterInterface', 'Drupal\replication\Annotation\ReplicationFilter');
+    $this->setCacheBackend($cache_backend, 'replication_filters');
+  }
+
+}
diff --git a/src/Plugin/ReplicationFilterManagerInterface.php b/src/Plugin/ReplicationFilterManagerInterface.php
new file mode 100644
index 0000000..29acec7
--- /dev/null
+++ b/src/Plugin/ReplicationFilterManagerInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\replication\Plugin;
+
+use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
+use Drupal\Component\Plugin\PluginManagerInterface;
+
+/**
+ * Manages ReplicationFilter plugin implementations.
+ *
+ * @see \Drupal\replication\Annotation\ReplicationFilter
+ * @see \Drupal\replication\Plugin\ReplicationFilterInterface
+ * @see \Drupal\replication\Plugin\ReplicationFilter\ReplicationFilterBase
+ * @see plugin_api
+ */
+interface ReplicationFilterManagerInterface extends PluginManagerInterface, CachedDiscoveryInterface {
+
+}
diff --git a/src/ReplicationTask/ReplicationTask.php b/src/ReplicationTask/ReplicationTask.php
new file mode 100644
index 0000000..a332c6e
--- /dev/null
+++ b/src/ReplicationTask/ReplicationTask.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Drupal\replication\ReplicationTask;
+
+use Drupal\replication\ReplicationTask\ReplicationTaskInterface;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * {@inheritdoc}
+ */
+class ReplicationTask implements ReplicationTaskInterface {
+
+  /**
+   * @var string
+   *   The id of the filter plugin to use during replication.
+   */
+  protected $filterName;
+
+  /**
+   * @var ParameterBag
+   *   The parameters passed to the filter function.
+   */
+  protected $parameters;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setFilter($filter_name = NULL) {
+    $this->filterName = $filter_name;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFilter() {
+    return $this->filterName;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setParameters(ParameterBag $parameters = NULL) {
+    $this->parameters = $parameters;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setParametersByArray(array $parameters_array = array()) {
+    $parameters = new ParameterBag($parameters_array);
+    return $this->setParameters($parameters);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setParameter($name, $value) {
+    if (!$this->parameters instanceof ParameterBag) {
+      $parameters = new ParameterBag();
+      $this->setParameters($parameters);
+    }
+    $this->parameters->set($name, $value);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getParameters() {
+    return $this->parameters;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getParametersAsArray() {
+    return $this->parameters->all();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getParameter($name) {
+    return $this->parameters->get($name);
+  }
+
+}
diff --git a/src/ReplicationTask/ReplicationTaskInterface.php b/src/ReplicationTask/ReplicationTaskInterface.php
new file mode 100644
index 0000000..f88978c
--- /dev/null
+++ b/src/ReplicationTask/ReplicationTaskInterface.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace Drupal\replication\ReplicationTask;
+
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * The replication settings between source and target.
+ *
+ * This interface defines the optional settings to be used during a replication
+ * task between a source and a target workspace. These are based on CouchDB's
+ * replication specifications.
+ *
+ * @see http://docs.couchdb.org/en/latest/json-structure.html#replication-settings
+ */
+interface ReplicationTaskInterface {
+
+  /**
+   * Set the id of the filter plugin to use during replication.
+   *
+   * @param string $filter_name
+   *   The plugin id of a ReplicationFilterInterface.
+   *
+   * @return ReplicationTaskInterface
+   *   Returns $this.
+   */
+  public function setFilter($filter_name = NULL);
+
+  /**
+   * Get the id of the filter plugin to use during replication.
+   *
+   * @return string
+   *   The plugin id of a ReplicationFilterInterface.
+   */
+  public function getFilter();
+
+  /**
+   * Set the parameters for the filter plugin.
+   *
+   * @param ParameterBag $parameters
+   *   The parameters passed to the filter function.
+   *
+   * @return ReplicationTaskInterface
+   *   Returns $this.
+   */
+  public function setParameters(ParameterBag $parameters = NULL);
+
+  /**
+   * Set the parameters for the filter plugin using an array.
+   *
+   * The array input is converted to a ParameterBag and then passed to
+   * setParameters.
+   *
+   * @param array $parameters_array
+   *   An associative array of name-value parameters.
+   *
+   * @return ReplicationTaskInterface
+   *   Returns $this.
+   */
+  public function setParametersByArray(array $parameters_array = array());
+
+  /**
+   * Set a parameter for the filter plugin.
+   *
+   * If no parameter bag yet exists, an empty parameter bag will be created.
+   *
+   * @param string $name
+   *   The parameter name to set.
+   * @param string $value
+   *   The value for the parameter.
+   *
+   * @return ReplicationTaskInterface
+   *   Returns $this.
+   */
+  public function setParameter($name, $value);
+
+  /**
+   * Get the parameters for the filter plugin.
+   *
+   * @return ParameterBag
+   *   The parameters passed to the filter plugin.
+   */
+  public function getParameters();
+
+  /**
+   * Converts the parameter bag to an associative array and returns the array.
+   *
+   * @return string[string]
+   *   An associative array of parameters passed to the filter fn.
+   */
+  public function getParametersAsArray();
+
+  /**
+   * Get a parameter's value.
+   *
+   * @param string $name
+   *   The parameter name.
+   *
+   * @return mixed
+   *   The parameter value.
+   *
+   * @throws \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException
+   *   If the parameter is not defined.
+   */
+  public function getParameter($name);
+
+}
diff --git a/tests/src/Functional/ReplicationFilterTest.php b/tests/src/Functional/ReplicationFilterTest.php
new file mode 100644
index 0000000..67fab18
--- /dev/null
+++ b/tests/src/Functional/ReplicationFilterTest.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Drupal\Tests\replication\Functional;
+
+use Drupal\multiversion\Entity\Workspace;
+use Drupal\node\Entity\Node;
+use Drupal\simpletest\WebTestBase;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Tests replication filters.
+ *
+ * @group replication
+ */
+class ReplicationFilterTest extends WebTestBase {
+
+  protected $strictConfigSchema = FALSE;
+
+  public static $modules = [
+    'multiversion',
+    'node',
+    'user',
+    'replication',
+  ];
+
+  /**
+   * @var \Drupalser\Entity\User
+   *   The logged in user.
+   */
+  protected $user;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Create Basic page and Article node types.
+    if ($this->profile != 'standard') {
+      $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
+    }
+
+    $this->user = $this->drupalCreateUser(['administer workspaces']);
+    $this->drupalLogin($this->user);
+  }
+
+  /**
+   * Test filtering the changeset by UUIDs.
+   */
+  public function testUuidsFilter() {
+    $container = \Drupal::getContainer();
+    $changes_factory = $container->get('replication.changes_factory');
+
+    $workspace = Workspace::create(['machine_name' => 'default', 'type' => 'basic']);
+    $workspace->save();
+
+    $entity1 = Node::create([
+      'type' => 'article',
+      'title' => 'Test Entity 1',
+      'uid' => $this->user->id(),
+    ]);
+    $entity1->workspace = $workspace;
+    $entity1->save();
+
+    $entity2 = Node::create([
+      'type' => 'article',
+      'title' => 'Test Entity 2',
+      'uid' => $this->user->id(),
+    ]);
+    $entity2->workspace = $workspace;
+    $entity2->save();
+
+    $parameters = new ParameterBag(['uuids' => $entity1->uuid()]);
+    $changes = $changes_factory->get($workspace)->filter('uuid')->parameters($parameters)->getNormal();
+    $this->assertEqual(1, count($changes), 'Expect there is 1 entity in the changeset.');
+  }
+
+  /**
+   * Test filtering the changeset with the published filter.
+   */
+  public function testPublishedFilter() {
+    $container = \Drupal::getContainer();
+    $changes_factory = $container->get('replication.changes_factory');
+
+    $workspace = Workspace::create(['machine_name' => 'default', 'type' => 'basic']);
+    $workspace->save();
+
+    $entity1 = Node::create([
+      'type' => 'article',
+      'title' => 'Test Entity 1',
+      'uid' => $this->user->id(),
+      'status' => TRUE,
+    ]);
+    $entity1->workspace = $workspace;
+    $entity1->save();
+
+    $entity2 = Node::create([
+      'type' => 'article',
+      'title' => 'Test Entity 2',
+      'uid' => $this->user->id(),
+      'status' => FALSE,
+    ]);
+    $entity2->workspace = $workspace;
+    $entity2->save();
+
+    $changes = $changes_factory->get($workspace)->filter('published')->getNormal();
+    $this->assertEqual(1, count($changes), 'Expect there is 1 entity in the changeset.');
+  }
+
+  /**
+   * Test filtering the changeset with the entity type filter.
+   */
+  public function testEntityTypeFilter() {
+    $container = \Drupal::getContainer();
+    $changes_factory = $container->get('replication.changes_factory');
+
+    $this->drupalCreateContentType(['type' => 'article2', 'name' => 'Article2']);
+
+    $workspace = Workspace::create(['machine_name' => 'default', 'type' => 'basic']);
+    $workspace->save();
+
+    $entity1 = Node::create([
+      'type' => 'article',
+      'title' => 'Test Entity 1',
+      'uid' => $this->user->id(),
+      'status' => TRUE,
+    ]);
+    $entity1->workspace = $workspace;
+    $entity1->save();
+
+    $entity2 = Node::create([
+      'type' => 'article2',
+      'title' => 'Test Entity 2',
+      'uid' => $this->user->id(),
+      'status' => FALSE,
+    ]);
+    $entity2->workspace = $workspace;
+    $entity2->save();
+
+    $parameters = new ParameterBag(['entity_type' => 'article']);
+    $changes = $changes_factory->get($workspace)->filter('entity_type')->parameters($parameters)->getNormal();
+    $this->assertEqual(1, count($changes), 'Expect there is 1 entity in the changeset.');
+  }
+
+}
diff --git a/tests/src/Unit/Plugin/ReplicationFilter/EntityTypeFilterTest.php b/tests/src/Unit/Plugin/ReplicationFilter/EntityTypeFilterTest.php
new file mode 100644
index 0000000..4d97d94
--- /dev/null
+++ b/tests/src/Unit/Plugin/ReplicationFilter/EntityTypeFilterTest.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\Tests\replication\Unit\Plugin\ReplicationFilter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\replication\Plugin\ReplicationFilter\EntityTypeFilter;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Tests that the entity type filter parses parameters correctly.
+ *
+ * @group replication
+ */
+class EntityTypeFilterTest extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * Test filtering entity types.
+   *
+   * @dataProvider filterTestProvider
+   */
+  public function testFilter($entity_type, $parameter_value, $expected) {
+    // Use a mock builder for the class under test to eliminate the need to
+    // mock all the dependencies. This is OK since the method under test is a
+    // pure function, i.e. does not use the state createdy by the constructor.
+    $filter = $this->getMockBuilder(EntityTypeFilter::class)
+      ->disableOriginalConstructor()
+      ->setMethods(NULL)
+      ->getMock();
+    $entity = $this->getMock(EntityInterface::class);
+    $entity->method('bundle')
+      ->willReturn('article');
+    $parameters = new ParameterBag(['entity_type' => $parameter_value]);
+
+    $value = $filter->filter($entity, $parameters);
+
+    $this->assertEquals($expected, $value);
+  }
+
+  /**
+   * Provide test cases for the "entity_type" parameter.
+   */
+  public function filterTestProvider() {
+    return [
+      // Test singular parameter values.
+      ['article', 'article', TRUE],
+      ['article', 'page', FALSE],
+      // Test multiple parameter values.
+      ['article', 'page,article', TRUE],
+      ['article', 'article,page', TRUE],
+      ['article', 'page,news', FALSE],
+      // Test bad data that might be entered into the parameters:
+      ['article', '', FALSE],
+      ['article', NULL, FALSE],
+      ['article', FALSE, FALSE],
+      ['article', TRUE, FALSE],
+      ['article', 0, FALSE],
+    ];
+  }
+
+}
diff --git a/tests/src/Unit/Plugin/ReplicationFilter/UuidFilterTest.php b/tests/src/Unit/Plugin/ReplicationFilter/UuidFilterTest.php
new file mode 100644
index 0000000..a16be60
--- /dev/null
+++ b/tests/src/Unit/Plugin/ReplicationFilter/UuidFilterTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Drupal\Tests\replication\Unit\Plugin\ReplicationFilter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\replication\Plugin\ReplicationFilter\UuidFilter;
+use Symfony\Component\HttpFoundation\ParameterBag;
+
+/**
+ * Tests that the uuid filter parses parameters correctly.
+ *
+ * @group replication
+ */
+class UuidFilterTest extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * Test filtering UUIDs.
+   *
+   * @dataProvider filterTestProvider
+   */
+  public function testFilter($uuid, $parameter_value, $expected) {
+    // Use a mock builder for the class under test to eliminate the need to
+    // mock all the dependencies. This is OK since the method under test is a
+    // pure function, i.e. does not use the state createdy by the constructor.
+    $filter = $this->getMockBuilder(UuidFilter::class)
+      ->disableOriginalConstructor()
+      ->setMethods(NULL)
+      ->getMock();
+    $entity = $this->getMock(EntityInterface::class);
+    $entity->method('uuid')
+      ->willReturn($uuid);
+    $parameters = new ParameterBag(['uuids' => $parameter_value]);
+
+    $value = $filter->filter($entity, $parameters);
+
+    $this->assertEquals($expected, $value);
+  }
+
+  /**
+   * Provide test cases for the "uuids" parameter.
+   */
+  public function filterTestProvider() {
+    return [
+      // Test singular parameter values.
+      ['123', '123', TRUE],
+      ['123', '456', FALSE],
+      // Test multiple parameter values.
+      ['123', '123,456', TRUE],
+      ['123', '456,789', FALSE],
+      // Test bad data that might be entered into the parameters:
+      ['123', '123, 456', TRUE],
+      ['123', '123 , 456', TRUE],
+      ['123', '0', FALSE],
+      ['123', 'NULL', FALSE],
+    ];
+  }
+
+  /**
+   * Test filtering UUIDs with no parameter.
+   */
+  public function testFilterNoParameter() {
+    // Use a mock builder for the class under test to eliminate the need to
+    // mock all the dependencies. This is OK since the method under test is a
+    // pure function, i.e. does not use the state createdy by the constructor.
+    $filter = $this->getMockBuilder(UuidFilter::class)
+      ->disableOriginalConstructor()
+      ->setMethods(NULL)
+      ->getMock();
+    $entity = $this->getMock(EntityInterface::class);
+    $entity->method('uuid')
+      ->willReturn('123');
+    $parameters = new ParameterBag();
+
+    $value = $filter->filter($entity, $parameters);
+
+    $this->assertEquals(FALSE, $value);
+  }
+
+}
