From c190262fce2ae41e771c955a11106edc3cec6a47 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 16:41:43 -0300
Subject: [PATCH 01/12] package/pnpm

---
 components/utopian_labs/package.json |  5 ++++-
 pnpm-lock.yaml                       | 14 +++++---------
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/components/utopian_labs/package.json b/components/utopian_labs/package.json
index 7645ebb180ea9..c91d1bdea86ea 100644
--- a/components/utopian_labs/package.json
+++ b/components/utopian_labs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@pipedream/utopian_labs",
-  "version": "0.0.1",
+  "version": "0.1.0",
   "description": "Pipedream Utopian Labs Components",
   "main": "utopian_labs.app.mjs",
   "keywords": [
@@ -11,5 +11,8 @@
   "author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
   "publishConfig": {
     "access": "public"
+  },
+  "dependencies": {
+    "@pipedream/platform": "^3.0.3"
   }
 }
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1dfcf62479279..f36b2c3d14db7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14033,7 +14033,11 @@ importers:
 
   components/usps: {}
 
-  components/utopian_labs: {}
+  components/utopian_labs:
+    dependencies:
+      '@pipedream/platform':
+        specifier: ^3.0.3
+        version: 3.0.3
 
   components/utradea: {}
 
@@ -15468,14 +15472,6 @@ importers:
         specifier: ^6.0.0
         version: 6.2.0
 
-  modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {}
-
-  modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {}
-
-  modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {}
-
-  modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {}
-
   packages/ai:
     dependencies:
       '@pipedream/sdk':

From e79e0ed8b6adc12f552897b30e16294df84a389a Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 16:54:45 -0300
Subject: [PATCH 02/12] app/package base

---
 components/utopian_labs/package.json         |  2 +-
 components/utopian_labs/utopian_labs.app.mjs |  9 ++++++---
 pnpm-lock.yaml                               | 16 +++++++++++++---
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/components/utopian_labs/package.json b/components/utopian_labs/package.json
index c91d1bdea86ea..c6d91ce78be13 100644
--- a/components/utopian_labs/package.json
+++ b/components/utopian_labs/package.json
@@ -13,6 +13,6 @@
     "access": "public"
   },
   "dependencies": {
-    "@pipedream/platform": "^3.0.3"
+    "utopianlabs": "^0.1.11"
   }
 }
\ No newline at end of file
diff --git a/components/utopian_labs/utopian_labs.app.mjs b/components/utopian_labs/utopian_labs.app.mjs
index 56cad7a7de32f..b95c1ac50c684 100644
--- a/components/utopian_labs/utopian_labs.app.mjs
+++ b/components/utopian_labs/utopian_labs.app.mjs
@@ -1,11 +1,14 @@
+import { UtopianLabs } from "utopianlabs";
+
 export default {
   type: "app",
   app: "utopian_labs",
   propDefinitions: {},
   methods: {
-    // this.$auth contains connected account data
-    authKeys() {
-      console.log(Object.keys(this.$auth));
+    _getClient() {
+      return new UtopianLabs({
+        apiKey: this.$auth.api_key,
+      });
     },
   },
 };
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f36b2c3d14db7..7f9c4a7b4edfc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14035,9 +14035,9 @@ importers:
 
   components/utopian_labs:
     dependencies:
-      '@pipedream/platform':
-        specifier: ^3.0.3
-        version: 3.0.3
+      utopianlabs:
+        specifier: ^0.1.11
+        version: 0.1.11
 
   components/utradea: {}
 
@@ -29775,6 +29775,9 @@ packages:
     resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
     engines: {node: '>= 0.4.0'}
 
+  utopianlabs@0.1.11:
+    resolution: {integrity: sha512-72vBjQ3/hZHpXYQ6MuOTtcg29xAMSMEL0BFWGN6sgt4bHzPt+p2JwJPEgTTeMs5wP9cpAT1H4Bad4DOqLwRCiw==}
+
   uue@3.1.2:
     resolution: {integrity: sha512-axKLXVqwtdI/czrjG0X8hyV1KLgeWx8F4KvSbvVCnS+RUvsQMGRjx0kfuZDXXqj0LYvVJmx3B9kWlKtEdRrJLg==}
 
@@ -50103,6 +50106,13 @@ snapshots:
 
   utils-merge@1.0.1: {}
 
+  utopianlabs@0.1.11:
+    dependencies:
+      axios: 1.9.0
+      zod: 3.24.4
+    transitivePeerDependencies:
+      - debug
+
   uue@3.1.2:
     dependencies:
       escape-string-regexp: 1.0.5

From 3f56c914bc8aacf41bf81d4bf6dc86e0919885f9 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 18:30:34 -0300
Subject: [PATCH 03/12] Get Run Status action

---
 .../actions/get-run-status/get-run-status.mjs | 22 +++++++++++++++++++
 components/utopian_labs/utopian_labs.app.mjs  | 10 ++++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 components/utopian_labs/actions/get-run-status/get-run-status.mjs

diff --git a/components/utopian_labs/actions/get-run-status/get-run-status.mjs b/components/utopian_labs/actions/get-run-status/get-run-status.mjs
new file mode 100644
index 0000000000000..dc6de1297eb61
--- /dev/null
+++ b/components/utopian_labs/actions/get-run-status/get-run-status.mjs
@@ -0,0 +1,22 @@
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-get-run-status",
+  name: "Get Run Status",
+  description: "Retrieve the status of an initiated run. [See the documentation](https://docs.utopianlabs.ai/research#retrieve-research-run-status)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    runId: {
+      type: "string",
+      label: "Run ID",
+      description: "The ID of the run you want to retrieve the status for.",
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.getRunStatus(this.runId);
+    $.export("$summary", `Successfully retrieved status for run ${this.runId}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/utopian_labs.app.mjs b/components/utopian_labs/utopian_labs.app.mjs
index b95c1ac50c684..a7669770f9a20 100644
--- a/components/utopian_labs/utopian_labs.app.mjs
+++ b/components/utopian_labs/utopian_labs.app.mjs
@@ -5,10 +5,18 @@ export default {
   app: "utopian_labs",
   propDefinitions: {},
   methods: {
-    _getClient() {
+    _client() {
       return new UtopianLabs({
         apiKey: this.$auth.api_key,
       });
     },
+    initiateRun(args) {
+      return this._client().agents.runs.create(args);
+    },
+    getRunStatus(run) {
+      return this._client().agents.runs.get({
+        run,
+      });
+    },
   },
 };

From d31193e9198edea72005b26aeb10bbfc49437b9e Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 20:38:21 -0300
Subject: [PATCH 04/12] Initiate Research Run + utils

---
 .../actions/get-run-status/get-run-status.mjs |  2 +-
 .../initiate-research-run.mjs                 | 72 +++++++++++++++++++
 components/utopian_labs/common/utils.mjs      | 34 +++++++++
 components/utopian_labs/package.json          |  3 +-
 components/utopian_labs/utopian_labs.app.mjs  |  8 ++-
 5 files changed, 116 insertions(+), 3 deletions(-)
 create mode 100644 components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
 create mode 100644 components/utopian_labs/common/utils.mjs

diff --git a/components/utopian_labs/actions/get-run-status/get-run-status.mjs b/components/utopian_labs/actions/get-run-status/get-run-status.mjs
index dc6de1297eb61..8678040dac957 100644
--- a/components/utopian_labs/actions/get-run-status/get-run-status.mjs
+++ b/components/utopian_labs/actions/get-run-status/get-run-status.mjs
@@ -11,7 +11,7 @@ export default {
     runId: {
       type: "string",
       label: "Run ID",
-      description: "The ID of the run you want to retrieve the status for.",
+      description: "The ID of the run you want to retrieve the status for",
     },
   },
   async run({ $ }) {
diff --git a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
new file mode 100644
index 0000000000000..2dc107c5513b5
--- /dev/null
+++ b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
@@ -0,0 +1,72 @@
+import {
+  parseObjectEntries, parseStringAsJSON,
+} from "../../common/utils.mjs";
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-initiate-research-run",
+  name: "Initiate Research Run",
+  description: "Initiate a research run of the R1 agent. [See the documentation](https://docs.utopianlabs.ai/research#initiate-a-research-run)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    agent: {
+      propDefinition: [
+        utopianLabs,
+        "agent",
+      ],
+      options: [
+        {
+          label: "r1 - a more powerful agent that has access to a larger set of research sources",
+          value: "r1",
+        },
+        {
+          label: "r1-light - a more affordable version of R1",
+          value: "r1-light",
+        },
+      ],
+    },
+    lead: {
+      type: "object",
+      label: "Lead",
+      description: "The lead to research. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    minResearchSteps: {
+      type: "integer",
+      label: "Minimum Research Steps",
+      description: "Optionally limit R1 to a minimum amount of research steps (default is 0)",
+      optional: true,
+    },
+    maxResearchSteps: {
+      type: "integer",
+      label: "Maximum Research Steps",
+      description: "Optionally limit R1 to a maximum amount of research steps (default is 5)",
+      optional: true,
+    },
+    context: {
+      type: "string",
+      label: "Context",
+      description: "The context for the research run. This is a free-form string that will be used to guide R1's research",
+      optional: true,
+    },
+    additionalOptions: {
+      type: "object",
+      label: "Additional Options",
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/research#initiate-a-research-run) for all available parameters. Values will be parsed as JSON where applicable.",
+      optional: true,
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.initiateRun({
+      agent: this.agent,
+      lead: parseStringAsJSON(this.lead),
+      min_research_steps: this.minResearchSteps,
+      max_research_steps: this.maxResearchSteps,
+      context: this.context,
+      ...parseObjectEntries(this.additionalOptions),
+    });
+    $.export("$summary", `Successfully initiated run (ID: ${response.runId}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/common/utils.mjs b/components/utopian_labs/common/utils.mjs
new file mode 100644
index 0000000000000..2fc6d2fce24d9
--- /dev/null
+++ b/components/utopian_labs/common/utils.mjs
@@ -0,0 +1,34 @@
+import { ConfigurationError } from "@pipedream/platform";
+
+function optionalParseAsJSON(value) {
+  try {
+    return JSON.parse(value);
+  } catch (e) {
+    return value;
+  }
+}
+
+export function parseObjectEntries(value) {
+  const obj = typeof value === "string"
+    ? JSON.parse(value)
+    : value;
+  return Object.fromEntries(
+    Object.entries(obj).map(([
+      key,
+      value,
+    ]) => [
+      key,
+      optionalParseAsJSON(value),
+    ]),
+  );
+}
+
+export function parseStringAsJSON(value) {
+  try {
+    return typeof value === "string"
+      ? JSON.parse(value)
+      : value;
+  } catch (err) {
+    throw new ConfigurationError(`Error parsing JSON string: ${err}`);
+  }
+}
diff --git a/components/utopian_labs/package.json b/components/utopian_labs/package.json
index c6d91ce78be13..8cf157e5b4c72 100644
--- a/components/utopian_labs/package.json
+++ b/components/utopian_labs/package.json
@@ -13,6 +13,7 @@
     "access": "public"
   },
   "dependencies": {
-    "utopianlabs": "^0.1.11"
+    "utopianlabs": "^0.1.11",
+    "@pipedream/platform": "^3.0.3"
   }
 }
\ No newline at end of file
diff --git a/components/utopian_labs/utopian_labs.app.mjs b/components/utopian_labs/utopian_labs.app.mjs
index a7669770f9a20..63951e5a340a1 100644
--- a/components/utopian_labs/utopian_labs.app.mjs
+++ b/components/utopian_labs/utopian_labs.app.mjs
@@ -3,7 +3,13 @@ import { UtopianLabs } from "utopianlabs";
 export default {
   type: "app",
   app: "utopian_labs",
-  propDefinitions: {},
+  propDefinitions: {
+    agent: {
+      type: "string",
+      label: "Agent",
+      description: "The agent to run",
+    },
+  },
   methods: {
     _client() {
       return new UtopianLabs({

From 06428f63b97f9c9f52d2c9a30d199eecd00abc27 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 20:39:24 -0300
Subject: [PATCH 05/12] pnpm

---
 pnpm-lock.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7f9c4a7b4edfc..51ecb5423e0ca 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14035,6 +14035,9 @@ importers:
 
   components/utopian_labs:
     dependencies:
+      '@pipedream/platform':
+        specifier: ^3.0.3
+        version: 3.0.3
       utopianlabs:
         specifier: ^0.1.11
         version: 0.1.11

From d067bec5c681d8118ec0bb144b839edcefd28598 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 20:51:24 -0300
Subject: [PATCH 06/12] Adjustments

---
 .../actions/initiate-research-run/initiate-research-run.mjs     | 2 +-
 components/utopian_labs/common/utils.mjs                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
index 2dc107c5513b5..e9e78098e4893 100644
--- a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
+++ b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
@@ -66,7 +66,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.runId}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
     return response;
   },
 };
diff --git a/components/utopian_labs/common/utils.mjs b/components/utopian_labs/common/utils.mjs
index 2fc6d2fce24d9..3543973753653 100644
--- a/components/utopian_labs/common/utils.mjs
+++ b/components/utopian_labs/common/utils.mjs
@@ -8,7 +8,7 @@ function optionalParseAsJSON(value) {
   }
 }
 
-export function parseObjectEntries(value) {
+export function parseObjectEntries(value = {}) {
   const obj = typeof value === "string"
     ? JSON.parse(value)
     : value;

From 335ac53b46f8ad217571a63c92b6c63b668851e0 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 21:05:05 -0300
Subject: [PATCH 07/12] Initiate Qualification Run + reusing props

---
 .../initiate-qualification-run.mjs            | 75 +++++++++++++++++++
 .../initiate-research-run.mjs                 | 39 +++++-----
 components/utopian_labs/utopian_labs.app.mjs  | 29 +++++++
 3 files changed, 124 insertions(+), 19 deletions(-)
 create mode 100644 components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs

diff --git a/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs b/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs
new file mode 100644
index 0000000000000..4cd2e1c917c8c
--- /dev/null
+++ b/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs
@@ -0,0 +1,75 @@
+import {
+  parseObjectEntries, parseStringAsJSON,
+} from "../../common/utils.mjs";
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-initiate-qualification-run",
+  name: "Initiate Qualification Run",
+  description: "Initiate a qualification run of the R1-Qualification agent. [See the documentation](https://docs.utopianlabs.ai/qualification#initiate-a-qualification-run)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    agent: {
+      propDefinition: [
+        utopianLabs,
+        "agent",
+      ],
+      options: [
+        {
+          label: "r1-qualification - the default research agent, which has access to a larger set of research sources",
+          value: "r1-qualification",
+        },
+        {
+          label: "r1-qualification-light - the light research agent, more affordable",
+          value: "r1-qualification-light",
+        },
+      ],
+    },
+    lead: {
+      propDefinition: [
+        utopianLabs,
+        "lead",
+      ],
+      description: "The lead to qualify. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    minResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "minResearchSteps",
+      ],
+    },
+    maxResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "maxResearchSteps",
+      ],
+    },
+    context: {
+      propDefinition: [
+        utopianLabs,
+        "context",
+      ],
+    },
+    additionalOptions: {
+      propDefinition: [
+        utopianLabs,
+        "additionalOptions",
+      ],
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/qualification#initiate-a-qualification-run) for all available parameters. Values will be parsed as JSON where applicable.",
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.initiateRun({
+      agent: this.agent,
+      lead: parseStringAsJSON(this.lead),
+      min_research_steps: this.minResearchSteps,
+      max_research_steps: this.maxResearchSteps,
+      context: this.context,
+      ...parseObjectEntries(this.additionalOptions),
+    });
+    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
index e9e78098e4893..1d9c6b0f3f939 100644
--- a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
+++ b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
@@ -28,33 +28,34 @@ export default {
       ],
     },
     lead: {
-      type: "object",
-      label: "Lead",
-      description: "The lead to research. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+      propDefinition: [
+        utopianLabs,
+        "lead",
+      ],
     },
     minResearchSteps: {
-      type: "integer",
-      label: "Minimum Research Steps",
-      description: "Optionally limit R1 to a minimum amount of research steps (default is 0)",
-      optional: true,
+      propDefinition: [
+        utopianLabs,
+        "minResearchSteps",
+      ],
     },
     maxResearchSteps: {
-      type: "integer",
-      label: "Maximum Research Steps",
-      description: "Optionally limit R1 to a maximum amount of research steps (default is 5)",
-      optional: true,
+      propDefinition: [
+        utopianLabs,
+        "maxResearchSteps",
+      ],
     },
     context: {
-      type: "string",
-      label: "Context",
-      description: "The context for the research run. This is a free-form string that will be used to guide R1's research",
-      optional: true,
+      propDefinition: [
+        utopianLabs,
+        "context",
+      ],
     },
     additionalOptions: {
-      type: "object",
-      label: "Additional Options",
-      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/research#initiate-a-research-run) for all available parameters. Values will be parsed as JSON where applicable.",
-      optional: true,
+      propDefinition: [
+        utopianLabs,
+        "additionalOptions",
+      ],
     },
   },
   async run({ $ }) {
diff --git a/components/utopian_labs/utopian_labs.app.mjs b/components/utopian_labs/utopian_labs.app.mjs
index 63951e5a340a1..cac2762b62f7b 100644
--- a/components/utopian_labs/utopian_labs.app.mjs
+++ b/components/utopian_labs/utopian_labs.app.mjs
@@ -9,6 +9,35 @@ export default {
       label: "Agent",
       description: "The agent to run",
     },
+    lead: {
+      type: "object",
+      label: "Lead",
+      description: "The lead to research. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    minResearchSteps: {
+      type: "integer",
+      label: "Minimum Research Steps",
+      description: "Optionally limit the agent to a minimum amount of research steps (default is 0)",
+      optional: true,
+    },
+    maxResearchSteps: {
+      type: "integer",
+      label: "Maximum Research Steps",
+      description: "Optionally limit the agent to a maximum amount of research steps (default is 5)",
+      optional: true,
+    },
+    context: {
+      type: "string",
+      label: "Context",
+      description: "The context for the run. This is a free-form string that will be used to guide the agent's research",
+      optional: true,
+    },
+    additionalOptions: {
+      type: "object",
+      label: "Additional Options",
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/research#initiate-a-research-run) for all available parameters. Values will be parsed as JSON where applicable.",
+      optional: true,
+    },
   },
   methods: {
     _client() {

From 861dfc5bcb0f28e92945b21adcd3b6387ffdfdf6 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 21:12:53 -0300
Subject: [PATCH 08/12] Classification and Timing runs

---
 .../initiate-classification-run.mjs           | 82 +++++++++++++++++++
 .../initiate-timing-run.mjs                   | 75 +++++++++++++++++
 components/utopian_labs/common/utils.mjs      |  8 ++
 3 files changed, 165 insertions(+)
 create mode 100644 components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
 create mode 100644 components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs

diff --git a/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs b/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
new file mode 100644
index 0000000000000..c20d74975872d
--- /dev/null
+++ b/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
@@ -0,0 +1,82 @@
+import {
+  parseArrayAsJSON,
+  parseObjectEntries, parseStringAsJSON,
+} from "../../common/utils.mjs";
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-initiate-classification-run",
+  name: "Initiate Classification Run",
+  description: "Initiate a classification run of the R1-Classification agent. [See the documentation](https://docs.utopianlabs.ai/classification#initiate-a-classification-run)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    agent: {
+      propDefinition: [
+        utopianLabs,
+        "agent",
+      ],
+      options: [
+        {
+          label: "r1-classification - the default research agent, which has access to a larger set of research sources",
+          value: "r1-classification",
+        },
+        {
+          label: "r1-classification-light - the light research agent, more affordable",
+          value: "r1-classification-light",
+        },
+      ],
+    },
+    lead: {
+      propDefinition: [
+        utopianLabs,
+        "lead",
+      ],
+      description: "The lead to determine the classification for. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    options: {
+      type: "string[]",
+      label: "Options",
+      description: "The options to classify the lead into (minimum 2, maximum 10). Each option should be an object such as: `{ \"name\": \"option name\", \"description\": \"option description\" }`",
+    },
+    minResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "minResearchSteps",
+      ],
+    },
+    maxResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "maxResearchSteps",
+      ],
+    },
+    context: {
+      propDefinition: [
+        utopianLabs,
+        "context",
+      ],
+    },
+    additionalOptions: {
+      propDefinition: [
+        utopianLabs,
+        "additionalOptions",
+      ],
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/classification#initiate-a-classification-run) for all available parameters. Values will be parsed as JSON where applicable.",
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.initiateRun({
+      agent: this.agent,
+      lead: parseStringAsJSON(this.lead),
+      options: parseArrayAsJSON(this.options),
+      min_research_steps: this.minResearchSteps,
+      max_research_steps: this.maxResearchSteps,
+      context: this.context,
+      ...parseObjectEntries(this.additionalOptions),
+    });
+    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs b/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs
new file mode 100644
index 0000000000000..008cb6ff41933
--- /dev/null
+++ b/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs
@@ -0,0 +1,75 @@
+import {
+  parseObjectEntries, parseStringAsJSON,
+} from "../../common/utils.mjs";
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-initiate-timing-run",
+  name: "Initiate Timing Run",
+  description: "Initiate a timing run of the R1-Timing agent. [See the documentation](https://docs.utopianlabs.ai/timing#initiate-a-timing-run)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    agent: {
+      propDefinition: [
+        utopianLabs,
+        "agent",
+      ],
+      options: [
+        {
+          label: "r1-timing - the default research agent, which has access to a larger set of research sources",
+          value: "r1-timing",
+        },
+        {
+          label: "r1-timing-light - the light research agent, more affordable",
+          value: "r1-timing-light",
+        },
+      ],
+    },
+    lead: {
+      propDefinition: [
+        utopianLabs,
+        "lead",
+      ],
+      description: "The lead to determine the timing for. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    minResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "minResearchSteps",
+      ],
+    },
+    maxResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "maxResearchSteps",
+      ],
+    },
+    context: {
+      propDefinition: [
+        utopianLabs,
+        "context",
+      ],
+    },
+    additionalOptions: {
+      propDefinition: [
+        utopianLabs,
+        "additionalOptions",
+      ],
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/timing#initiate-a-timing-run) for all available parameters. Values will be parsed as JSON where applicable.",
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.initiateRun({
+      agent: this.agent,
+      lead: parseStringAsJSON(this.lead),
+      min_research_steps: this.minResearchSteps,
+      max_research_steps: this.maxResearchSteps,
+      context: this.context,
+      ...parseObjectEntries(this.additionalOptions),
+    });
+    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/common/utils.mjs b/components/utopian_labs/common/utils.mjs
index 3543973753653..40131d337bca8 100644
--- a/components/utopian_labs/common/utils.mjs
+++ b/components/utopian_labs/common/utils.mjs
@@ -32,3 +32,11 @@ export function parseStringAsJSON(value) {
     throw new ConfigurationError(`Error parsing JSON string: ${err}`);
   }
 }
+
+export function parseArrayAsJSON(value) {
+  try {
+    return value.map((item) => JSON.parse(item));
+  } catch (err) {
+    throw new ConfigurationError(`Error parsing JSON string in array: ${err}`);
+  }
+}

From 0cbf137157187e581060137b39310727403fc45c Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 21:19:36 -0300
Subject: [PATCH 09/12] Initiate Copywriting Run

---
 .../initiate-copywriting-run.mjs              |  84 +++++++++
 components/utopian_labs/common/constants.mjs  | 178 ++++++++++++++++++
 2 files changed, 262 insertions(+)
 create mode 100644 components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
 create mode 100644 components/utopian_labs/common/constants.mjs

diff --git a/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs b/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
new file mode 100644
index 0000000000000..396fc0a7d7c69
--- /dev/null
+++ b/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
@@ -0,0 +1,84 @@
+import { LANGUAGE_CODE_OPTIONS } from "../../common/constants.mjs";
+import {
+  parseObjectEntries, parseStringAsJSON,
+} from "../../common/utils.mjs";
+import utopianLabs from "../../utopian_labs.app.mjs";
+
+export default {
+  key: "utopian_labs-initiate-copywriting-run",
+  name: "Initiate Copywriting Run",
+  description: "Initiate a copywriting run of the R1-Copywriting agent. [See the documentation](https://docs.utopianlabs.ai/copywriting#initiate-a-copywriting-run)",
+  version: "0.0.1",
+  type: "action",
+  props: {
+    utopianLabs,
+    agent: {
+      propDefinition: [
+        utopianLabs,
+        "agent",
+      ],
+      options: [
+        {
+          label: "r1-copywriting - the default research agent, which has access to a larger set of research sources",
+          value: "r1-copywriting",
+        },
+        {
+          label: "r1-copywriting-light - the light research agent, more affordable",
+          value: "r1-copywriting-light",
+        },
+      ],
+    },
+    lead: {
+      propDefinition: [
+        utopianLabs,
+        "lead",
+      ],
+      description: "The lead to write a sales message for. [See the documentation](https://docs.utopianlabs.ai/types#the-lead-type) for more information. Example: `{ \"company\": { \"website\": \"https://pipedream.com/\" } }`",
+    },
+    language: {
+      type: "string",
+      label: "Language",
+      description: "The langauge to write the copy in (defaults to `en-US`)",
+      optional: true,
+      options: LANGUAGE_CODE_OPTIONS,
+    },
+    minResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "minResearchSteps",
+      ],
+    },
+    maxResearchSteps: {
+      propDefinition: [
+        utopianLabs,
+        "maxResearchSteps",
+      ],
+    },
+    context: {
+      propDefinition: [
+        utopianLabs,
+        "context",
+      ],
+    },
+    additionalOptions: {
+      propDefinition: [
+        utopianLabs,
+        "additionalOptions",
+      ],
+      description: "Additional parameters to send in the request. [See the documentation](https://docs.utopianlabs.ai/copywriting#initiate-a-copywriting-run) for all available parameters. Values will be parsed as JSON where applicable.",
+    },
+  },
+  async run({ $ }) {
+    const response = await this.utopianLabs.initiateRun({
+      agent: this.agent,
+      lead: parseStringAsJSON(this.lead),
+      language: this.language,
+      min_research_steps: this.minResearchSteps,
+      max_research_steps: this.maxResearchSteps,
+      context: this.context,
+      ...parseObjectEntries(this.additionalOptions),
+    });
+    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    return response;
+  },
+};
diff --git a/components/utopian_labs/common/constants.mjs b/components/utopian_labs/common/constants.mjs
new file mode 100644
index 0000000000000..faa5e8d59e463
--- /dev/null
+++ b/components/utopian_labs/common/constants.mjs
@@ -0,0 +1,178 @@
+export const LANGUAGE_CODE_OPTIONS = [
+  {
+    label: "English (United States)",
+    value: "en-us",
+  },
+  {
+    label: "English (United Kingdom)",
+    value: "en-uk",
+  },
+  {
+    label: "English (Australia)",
+    value: "en-au",
+  },
+  {
+    label: "Dutch (Netherlands)",
+    value: "nl",
+  },
+  {
+    label: "German (Germany)",
+    value: "de",
+  },
+  {
+    label: "Luxembourgish (Luxembourg)",
+    value: "lb",
+  },
+  {
+    label: "French (France)",
+    value: "fr",
+  },
+  {
+    label: "Spanish (Spain and Latin America)",
+    value: "es",
+  },
+  {
+    label: "Portuguese (Portugal)",
+    value: "pt",
+  },
+  {
+    label: "Italian (Italy)",
+    value: "it",
+  },
+  {
+    label: "Greek (Greece)",
+    value: "gr",
+  },
+  {
+    label: "Russian (Russia)",
+    value: "ru",
+  },
+  {
+    label: "Turkish (Turkey)",
+    value: "tr",
+  },
+  {
+    label: "Danish (Denmark)",
+    value: "da",
+  },
+  {
+    label: "Swedish (Sweden)",
+    value: "sv",
+  },
+  {
+    label: "Finnish (Finland)",
+    value: "fi",
+  },
+  {
+    label: "Icelandic (Iceland)",
+    value: "is",
+  },
+  {
+    label: "Norwegian (Norway)",
+    value: "no",
+  },
+  {
+    label: "Chinese (China)",
+    value: "zh",
+  },
+  {
+    label: "Japanese (Japan)",
+    value: "ja",
+  },
+  {
+    label: "Hindi (India)",
+    value: "hi",
+  },
+  {
+    label: "Thai (Thailand)",
+    value: "th",
+  },
+  {
+    label: "Vietnamese (Vietnam)",
+    value: "vi",
+  },
+  {
+    label: "Burmese (Myanmar)",
+    value: "my",
+  },
+  {
+    label: "Korean (Korea)",
+    value: "ko",
+  },
+  {
+    label: "Estonian (Estonia)",
+    value: "et",
+  },
+  {
+    label: "Lithuanian (Lithuania)",
+    value: "lt",
+  },
+  {
+    label: "Latvian (Latvia)",
+    value: "lv",
+  },
+  {
+    label: "Macedonian (North Macedonia)",
+    value: "mk",
+  },
+  {
+    label: "Indonesian (Indonesia)",
+    value: "id",
+  },
+  {
+    label: "Czech (Czech Republic)",
+    value: "cs",
+  },
+  {
+    label: "Polish (Poland)",
+    value: "pl",
+  },
+  {
+    label: "Slovenian (Slovenia)",
+    value: "sl",
+  },
+  {
+    label: "Slovak (Slovakia)",
+    value: "sk",
+  },
+  {
+    label: "Bulgarian (Bulgaria)",
+    value: "bg",
+  },
+  {
+    label: "Bosnian (Bosnia)",
+    value: "bs",
+  },
+  {
+    label: "Hungarian (Hungary)",
+    value: "hu",
+  },
+  {
+    label: "Ukrainian (Ukraine)",
+    value: "uk",
+  },
+  {
+    label: "Serbian (Serbia)",
+    value: "sr",
+  },
+  {
+    label: "Romanian (Romania)",
+    value: "ro",
+  },
+  {
+    label: "Albanian (Albania)",
+    value: "sq",
+  },
+  {
+    label: "Armenian (Armenia)",
+    value: "hy",
+  },
+  {
+    label: "Hebrew (Israel)",
+    value: "he",
+  },
+  {
+    label: "Arabic (Various)",
+    value: "ar",
+  },
+];

From 657970847d4a3481758bb03b6d6480019302cd05 Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 21:49:56 -0300
Subject: [PATCH 10/12] eslint run

---
 components/utopian_labs/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/utopian_labs/package.json b/components/utopian_labs/package.json
index 8cf157e5b4c72..eaa55033b8aec 100644
--- a/components/utopian_labs/package.json
+++ b/components/utopian_labs/package.json
@@ -16,4 +16,4 @@
     "utopianlabs": "^0.1.11",
     "@pipedream/platform": "^3.0.3"
   }
-}
\ No newline at end of file
+}

From 8465db457fdb3a052fb9fc4e3ef6dc41200e78fc Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Thu, 22 May 2025 21:51:29 -0300
Subject: [PATCH 11/12] summary improvements

---
 .../initiate-classification-run/initiate-classification-run.mjs | 2 +-
 .../initiate-copywriting-run/initiate-copywriting-run.mjs       | 2 +-
 .../initiate-qualification-run/initiate-qualification-run.mjs   | 2 +-
 .../actions/initiate-research-run/initiate-research-run.mjs     | 2 +-
 .../actions/initiate-timing-run/initiate-timing-run.mjs         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs b/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
index c20d74975872d..c828d990c7b07 100644
--- a/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
+++ b/components/utopian_labs/actions/initiate-classification-run/initiate-classification-run.mjs
@@ -76,7 +76,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id})`);
     return response;
   },
 };
diff --git a/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs b/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
index 396fc0a7d7c69..56c1985e7f252 100644
--- a/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
+++ b/components/utopian_labs/actions/initiate-copywriting-run/initiate-copywriting-run.mjs
@@ -78,7 +78,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id})`);
     return response;
   },
 };
diff --git a/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs b/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs
index 4cd2e1c917c8c..88eef67c6cd33 100644
--- a/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs
+++ b/components/utopian_labs/actions/initiate-qualification-run/initiate-qualification-run.mjs
@@ -69,7 +69,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id})`);
     return response;
   },
 };
diff --git a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
index 1d9c6b0f3f939..1a64d01460a70 100644
--- a/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
+++ b/components/utopian_labs/actions/initiate-research-run/initiate-research-run.mjs
@@ -67,7 +67,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id})`);
     return response;
   },
 };
diff --git a/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs b/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs
index 008cb6ff41933..7f762a60a1992 100644
--- a/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs
+++ b/components/utopian_labs/actions/initiate-timing-run/initiate-timing-run.mjs
@@ -69,7 +69,7 @@ export default {
       context: this.context,
       ...parseObjectEntries(this.additionalOptions),
     });
-    $.export("$summary", `Successfully initiated run (ID: ${response.id}`);
+    $.export("$summary", `Successfully initiated run (ID: ${response.id})`);
     return response;
   },
 };

From 4503fcc26ef4e905f981a118761b789eac0f8e5f Mon Sep 17 00:00:00 2001
From: GTFalcao <gtfalcao96@gmail.com>
Date: Mon, 26 May 2025 23:00:34 -0300
Subject: [PATCH 12/12] Adjusting incorrect language codes

---
 components/utopian_labs/common/constants.mjs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/components/utopian_labs/common/constants.mjs b/components/utopian_labs/common/constants.mjs
index faa5e8d59e463..870ec1f9c4561 100644
--- a/components/utopian_labs/common/constants.mjs
+++ b/components/utopian_labs/common/constants.mjs
@@ -1,15 +1,15 @@
 export const LANGUAGE_CODE_OPTIONS = [
   {
     label: "English (United States)",
-    value: "en-us",
+    value: "en-US",
   },
   {
     label: "English (United Kingdom)",
-    value: "en-uk",
+    value: "en-UK",
   },
   {
     label: "English (Australia)",
-    value: "en-au",
+    value: "en-AU",
   },
   {
     label: "Dutch (Netherlands)",