diff --git a/apps/cli/utilities/aat_wrest/aat_wrest/metadata_wrester.py b/apps/cli/utilities/aat_wrest/aat_wrest/metadata_wrester.py
index 05e0d12a48262b9dd8496a300b25bb3a0f601649..5eeda69e8f0b684b14a47ed09edd573e25cdb1a7 100644
--- a/apps/cli/utilities/aat_wrest/aat_wrest/metadata_wrester.py
+++ b/apps/cli/utilities/aat_wrest/aat_wrest/metadata_wrester.py
@@ -348,3 +348,39 @@ class WrestWorkflowMetadata:
             self.conn.close()
 
         return make_json
+
+    def wrest_curator(self) -> json:
+        """
+        Given a locator, returns the product information necessary to run curator on it.
+
+        :return: JSON containing product information.
+        """
+        query = """
+        SELECT sp.science_product_type,
+               eb.telescope,
+               eb.project_code
+        FROM science_products sp
+        JOIN execution_blocks eb ON sp.science_product_locator = eb.science_product_locator
+        WHERE sp.science_product_locator = %(spl)s;
+        """
+        make_json = {}
+        try:
+            cursor = self.conn.cursor()
+            cursor.execute(query, {"spl": self.spl[0]})
+            data = cursor.fetchall()
+            if data:
+                make_json = json.dumps(
+                    {
+                        "product_type": str(data[0][0]).lower().replace(' ', '_'),
+                        "telescope": data[0][1],
+                        "projectCode": data[0][2]
+                    }
+                )
+            else:
+                self.logger.error(
+                    f"ERROR: aat-wrest query returned no results!"
+                    f" The database appears to be missing information for spl id {self.spl[0]}!"
+                )
+        finally:
+            self.conn.close()
+        return make_json
diff --git a/apps/cli/utilities/aat_wrest/aat_wrest/wrest.py b/apps/cli/utilities/aat_wrest/aat_wrest/wrest.py
index 375c7c67e16e0619587083027b6ade3f4aee8f22..8de40dcc8c0eb4ad7ee3ffa55952f7c571b98c78 100644
--- a/apps/cli/utilities/aat_wrest/aat_wrest/wrest.py
+++ b/apps/cli/utilities/aat_wrest/aat_wrest/wrest.py
@@ -107,6 +107,13 @@ def parser() -> argparse.ArgumentParser:
         required=False,
         help="Find the basic product information for the provided product locator(s)",
     )
+    arg_parser.add_argument(
+        "--curator",
+        nargs=1,
+        action="store",
+        required=False,
+        help="Find the product information necessary to run curator on the provided product locator",
+    )
     return arg_parser
 
 
@@ -140,6 +147,8 @@ def determine_wrester(connection: MDDBConnector, args: argparse.Namespace):
         data = json.dumps({"reimaging_locator": reimaging_locator, "parameter_locator": parameter_locator})
     elif args.product:
         data = WrestWorkflowMetadata(connection, spl=args.product).wrest_product_info()
+    elif args.curator:
+        data = WrestWorkflowMetadata(connection, spl=args.curator).wrest_curator()
     else:
         data = None
 
diff --git a/apps/web/src/app/workspaces/ws-home/ws-home.component.html b/apps/web/src/app/workspaces/ws-home/ws-home.component.html
index 31f2c9ae4ea54a6e3667f18c941a25f483247bab..5b2e845e8afac3784cbe04355d9249bae708d2a9 100644
--- a/apps/web/src/app/workspaces/ws-home/ws-home.component.html
+++ b/apps/web/src/app/workspaces/ws-home/ws-home.component.html
@@ -143,3 +143,50 @@
     </div>
   </div>
 </div>
+<div class="container border rounded py-3 my-3">
+  <h4>Curator</h4>
+  <div class="row p-3 mt-4">
+    <div class="col-6">
+      <div class="md-form">
+        <label for="curSplInput" class="">Science Product</label>
+        <input type="text" id="curSplInput" class="form-control"
+               (change)="setProductLocator($event.target.value)"/>
+      </div>
+    </div>
+    <div class="col-6">
+      <div class="md-form">
+        <label for="curDataInput" class="">Data Location (Optional)</label>
+        <input type="text" id="curDataInput" class="form-control"
+               (change)="setDataLocation($event.target.value)"/>
+      </div>
+    </div>
+    <div class="col-3">
+      <div class="md-form">
+        <label for="curTargetInput" class="">Target List (Optional)</label>
+        <input type="text" id="curTargetInput" class="form-control"
+               (change)="setTargetList($event.target.value)"/>
+      </div>
+    </div>
+    <div class="col-3">
+      <div class="md-form">
+        <label for="curUserEmail" class="">Email Address</label>
+        <input type="text" id="curUserEmail" class="form-control"
+               [value]="userEmail" (change)="setUserEmail($event.target.value)"/>
+      </div>
+    </div>
+  </div>
+  <div id="full-curator-button-container" class="d-flex justify-content-left py-2">
+    <div class="d-flex px-2">
+      <button type="button" class="btn btn-lg btn-primary" id="full-curator-submit"
+              (click)="LaunchCuratorCapabilityOnClick('full')">
+        Launch full curation
+      </button>
+    </div>
+    <div id="partial-curator-button-container" class="d-flex px-2">
+      <button type="button" class="btn btn-lg btn-info" id="partial-curator-submit"
+              (click)="LaunchCuratorCapabilityOnClick('partial')">
+        Launch partial curation
+      </button>
+    </div>
+  </div>
+</div>
diff --git a/apps/web/src/app/workspaces/ws-home/ws-home.component.ts b/apps/web/src/app/workspaces/ws-home/ws-home.component.ts
index 539dcd3248203672623476fe7e26a1bff8842029..e12f7d0ab6bd911fe37d1ad3b0bc474779b95c40 100644
--- a/apps/web/src/app/workspaces/ws-home/ws-home.component.ts
+++ b/apps/web/src/app/workspaces/ws-home/ws-home.component.ts
@@ -34,6 +34,8 @@ export class WsHomeComponent implements OnInit {
   public inputFileList: FileList;
   public cmsPath: string;
   public sdmId: string;
+  public dataLocation: string;
+  public targetList: string;
 
   constructor(
     private capabilityLauncher: CapabilityLauncherService,
@@ -117,6 +119,24 @@ export class WsHomeComponent implements OnInit {
     });
   }
 
+  /**
+   * OnClick method that creates a capability request for a curator capability and submits it with the parameters:
+   * - Curator type (full or partial)
+   * - EB Product Locator
+   * - Data location path
+   * - Target list
+   * - User email
+   */
+  LaunchCuratorCapabilityOnClick(curatorType: string): void {
+    this.launchCapability('curator', {
+      curator_type: curatorType,
+      product_locator: this.productLocator,
+      data_location: this.dataLocation,
+      target_list: this.targetList,
+      user_email: this.userEmail,
+    });
+  }
+
   /**
    * method that sets the user input Science Product Locator for the download capability
    * @param spl the Science Product Locator to download
@@ -165,6 +185,22 @@ export class WsHomeComponent implements OnInit {
     this.sdmId = id;
   }
 
+  /**
+   * Sets the data location for curator
+   * @param path Data location path for curator
+   */
+  setDataLocation(path: string): void {
+    this.dataLocation = path;
+  }
+
+  /**
+   * Sets the target list for curator
+   * @param targetList Target list for curator
+   */
+  setTargetList(targetList: string): void {
+    this.targetList = targetList;
+  }
+
   /**
    * Method that uses the capabilityLauncher service to launch a capability
    * @param capabilityName  Name of capability
diff --git a/shared/workspaces/alembic/versions/3eae1178cace_add_curator_workflow.py b/shared/workspaces/alembic/versions/3eae1178cace_add_curator_workflow.py
new file mode 100644
index 0000000000000000000000000000000000000000..05f522841b462b6b20f1ef6c9815c518d5bb2d4c
--- /dev/null
+++ b/shared/workspaces/alembic/versions/3eae1178cace_add_curator_workflow.py
@@ -0,0 +1,100 @@
+"""add curator workflow
+
+Revision ID: 3eae1178cace
+Revises: 61cbcd1d83f7
+Create Date: 2023-10-12 11:25:34.165586
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '3eae1178cace'
+down_revision = '61cbcd1d83f7'
+branch_labels = None
+depends_on = None
+
+wf_name = "curator"
+
+curator_condor = """executable = curator.sh
+arguments = metadata.json {{curator_type}}
+
+output = curator.out
+error = curator.err
+log = condor.log
+
+should_transfer_files = NO
++WantIOProxy = True
+request_memory = {{ramInGb}}
+getenv = True
+environment = "CAPO_PATH=/home/casa/capo"
+requirements = HasLustre == True
+
+queue
+
+"""
+
+curator_sh = """#!/bin/sh
+set -o errexit
+
+SBIN_PATH=/lustre/aoc/cluster/pipeline/$CAPO_PROFILE/workspaces/sbin
+
+${SBIN_PATH}/ingest_envoy curate --$2 $1
+
+"""
+
+metadata_json = """{
+  "product_locator": "{{product_locator}}",
+  "data_location": "{{data_location}}",
+  "product_type": "{{product_type}}",
+  "target_list": ["{{target_list}}"],
+  "projectMetadata": {
+    "telescope": "{{telescope}}",
+    "projectCode": "{{project_code}}"
+  }
+}
+"""
+
+
+def upgrade():
+    op.execute(
+        f"""
+        INSERT INTO workflows (workflow_name, requires_lustre) VALUES (E'{wf_name}', true)
+        """
+    )
+
+    op.execute(
+        f"""
+        INSERT INTO workflow_templates (filename, content, workflow_name)
+        VALUES ('curator.condor', E'{curator_condor}', E'{wf_name}')
+        """
+    )
+
+    op.execute(
+        f"""
+        INSERT INTO workflow_templates (filename, content, workflow_name)
+        VALUES ('curator.sh', E'{curator_sh}', E'{wf_name}')
+        """
+    )
+
+    op.execute(
+        f"""
+        INSERT INTO workflow_templates (filename, content, workflow_name)
+        VALUES ('metadata.json', E'{metadata_json}', E'{wf_name}')
+        """
+    )
+
+
+def downgrade():
+    op.execute(
+        f"""
+        DELETE FROM workflow_templates WHERE workflow_name = E'{wf_name}'
+        """
+    )
+
+    op.execute(
+        f"""
+        DELETE FROM workflows WHERE workflow_name = E'{wf_name}'
+        """
+    )
diff --git a/shared/workspaces/alembic/versions/5939146da7bb_add_curator_capability.py b/shared/workspaces/alembic/versions/5939146da7bb_add_curator_capability.py
new file mode 100644
index 0000000000000000000000000000000000000000..7650f177a93aa8412ef6946a1b9e79745ce8b81c
--- /dev/null
+++ b/shared/workspaces/alembic/versions/5939146da7bb_add_curator_capability.py
@@ -0,0 +1,48 @@
+"""add curator capability
+
+Revision ID: 5939146da7bb
+Revises: 3eae1178cace
+Create Date: 2023-10-23 22:04:43.801226
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '5939146da7bb'
+down_revision = '3eae1178cace'
+branch_labels = None
+depends_on = None
+
+wf_name = "curator"
+
+
+def upgrade():
+    op.execute(
+        f"""
+        INSERT INTO capabilities (capability_name, max_jobs, single_version_only)
+        VALUES (E'{wf_name}', 10, true)
+        """
+    )
+
+    op.execute(
+        f"""
+        INSERT INTO capability_state_machines (capability_name, machine_type, associated_workflows)
+        VALUES (E'{wf_name}', 'simple', '{{"workflow_name": "{wf_name}"}}')
+        """
+    )
+
+
+def downgrade():
+    op.execute(
+        f"""
+        DELETE FROM capability_state_machines WHERE capability_name = {wf_name}
+        """
+    )
+
+    op.execute(
+        f"""
+        DELETE FROM capabilities WHERE capability_name = {wf_name}
+        """
+    )
diff --git a/shared/workspaces/workspaces/workflow/services/workflow_service.py b/shared/workspaces/workspaces/workflow/services/workflow_service.py
index c1f52d4f4489bfa393102da67a40c3697c00eb6a..77dfed54b3c7e250314e37914a1364a89351c071 100644
--- a/shared/workspaces/workspaces/workflow/services/workflow_service.py
+++ b/shared/workspaces/workspaces/workflow/services/workflow_service.py
@@ -500,6 +500,8 @@ class WorkflowService(WorkflowServiceIF):
                     else parent_req.argument["sdmId"]
                 )
                 argument = eb
+        elif in_name("curator"):
+            wrest_type = "--curator"
         else:
             logger.info(f"No wrester found for workflow {name}. Does it actually require metadata?")
             return wf_request