Skip to content

agent.utils.job

Manage job tasks, submit results, and request new tasks. Accessed through agent.utils.job.

JobUtils Interface
interface JobUtils {
  submitTask(
    automationStatus: "running" | "success" | "failed" | "declined",
    data: Record<string, any>,
    finish: boolean,
    files: { name: string; extension: string; base64Data: string }[]
  ): Promise<{ success: false; error: string } | { success: true }>;

  submitTaskToAnotherJob(
    job_id: string,
    data: Record<string, any>,
    status?: "pending" | "failed" | "declined",
    files?: { name: string; extension: string; base64Data: string }[]
  ): Promise<
    { success: false; error: string } |
    { success: true; job_task_id: string; job_id: string }
  >;

  useAnotherTask(): Promise<{ job_task_id: string; job_proof: string } | null>;

  getCurrentTask(): Promise<
    { success: false; error: string } |
    { success: true; parent_task_id: string; job_proof: any, timeout: number }
  >;

  addSubTasks(job_variables, run_immediately?, job_id?, remote_device_id?): Promise<
    { success: false; error: string } |
    {
      success: true;
      inserted_ids: { planned_task_id: string; input: string }[];
      assignment_results?: { planned_task_id: string; assigned: boolean }[];
    }
  >;

  getSubTasks(planned_task_ids: string[]): Promise<
    { success: false; error: string } |
    { success: true; tasks: Record<string, { parent_task_id, comment, job_proof, timeout, status }> }
  >;
}

submitTask

Signature
submitTask(automationStatus: "running" | "success" | "failed" | "declined", data: Record<string, any>, finish: boolean, files: { name: string; extension: string; base64Data: string }[]): Promise<{ success: false; error: string } | { success: true }>

Submits the current task result to the server. Use this to report progress, success, or failure of job tasks. Once you call submitTask with finish=true, you cannot submit again for the same task. The files parameter is ignored when finish=false.

ParameterTypeDescription
automationStatus"running" | "success" | "failed" | "declined"Current status of the task
dataRecord<string, any>Task result data as key-value pairs
finishbooleanWhether this is the final submission. Once true, no more submissions are allowed for this task.
files{ name, extension, base64Data }[]Files to upload with the task. Ignored when finish=false.

Returns { success: true } | { success: false; error: string }Success status or error message

Submit successful task with data
const result = await agent.utils.job.submitTask(
  "success",
  { orderId: "12345", totalAmount: 99.99, itemsProcessed: 3 },
  true, // Final submission
  []    // No files
);

if (result.success) {
  console.log("Task submitted successfully");
}
Submit task with files
const screenshot = await agent.actions.screenshot(1080, 1920, 80);

const result = await agent.utils.job.submitTask(
  "success",
  { status: "completed" },
  true,
  [{ name: "confirmation", extension: "jpg", base64Data: screenshot.screenshot || "" }]
);
Report progress (not finished)
// files parameter is ignored when finish=false
await agent.utils.job.submitTask(
  "running",
  { currentStep: 3, totalSteps: 10 },
  false,
  []
);
Decline a task
await agent.utils.job.submitTask(
  "declined",
  { reason: "Item out of stock" },
  true,
  []
);

submitTaskToAnotherJob

Signature
submitTaskToAnotherJob(job_id: string, data: Record<string, any>, status?: "pending" | "failed" | "declined", files?: { name: string; extension: string; base64Data: string }[]): Promise<{ success: false; error: string } | { success: true; job_task_id: string; job_id: string }>

Writes a task into a separate "data-dump" job from inside a running automation. The target must be a devices_automation job with automation_id set and no planned tasks; the running job and target must share the same automation_id; and the running job's owner must own or have shared access to the target. Unlike submitTask (which updates the running task), this creates a brand-new task on a different job. job_proof must be JSON-serializable; attached files' public URLs are inlined into proof[name]. status defaults to "pending" and is independent of the running automation. Skips manual-mode gates and completion emails, and does not affect the running task's analytics. Backed by POST /api/v2/tasks/submit (automation data-dump branch).

ParameterTypeDescription
job_idstringID of the target data-dump job (devices_automation, automation_id set, no planned tasks).
dataRecord<string, any>Proof data; serialized to JSON and stored as job_proof on the new task.
status?"pending" | "failed" | "declined"Status of the new task on the target job. Defaults to "pending".
files?{ name, extension, base64Data }[]Optional files. Each is written to disk and its public URL embedded into the JSON proof under proof[name].

Returns { success: true; job_task_id: string; job_id: string } | { success: false; error: string }On success, the created task and target job ids; otherwise an error.

Push structured data into a sink job
const result = await agent.utils.job.submitTaskToAnotherJob(
  "68868530c189957861cd698a", // target data-dump job_id
  { email: "lead@example.com", name: "Jane Doe", capturedAt: Date.now() },
);
if (result.success) {
  console.log("Wrote dump task", result.job_task_id, "to job", result.job_id);
}
Attach a screenshot to the dump
const screenshot = await agent.actions.screenshot(1080, 1920, 80);

await agent.utils.job.submitTaskToAnotherJob(
  "68868530c189957861cd698a",
  { note: "Profile page state at capture" },
  "pending",
  [{ name: "snapshot", extension: ".jpg", base64Data: screenshot.screenshot || "" }],
);
Mark a dump as failed
await agent.utils.job.submitTaskToAnotherJob(
  "68868530c189957861cd698a",
  { reason: "captcha blocked" },
  "failed",
);

useAnotherTask

Signature
useAnotherTask(): Promise<{ job_task_id: string; job_proof: string } | null>

Accesses another task's data from the same job, allowing one job task to retrieve and use data from another. The target task must have set its automation variables with waiting: true via setAutomationVariables to be discoverable. Returns the task details or null if no waiting task is available.

Returns { job_task_id: string; job_proof: string } | nullTask details from another waiting task, or null if none available

Access data from another task in the same job
// First, the other task marks itself as waiting:
// await agent.utils.setAutomationVariables({ waiting: true });

const otherTask = await agent.utils.job.useAnotherTask();

if (otherTask) {
  console.log("Found waiting task:", otherTask.job_task_id);
  const proof = JSON.parse(otherTask.job_proof);
  const sharedData = proof.someSharedField;
} else {
  console.log("No waiting task available");
}
Coordinate between multiple tasks
// Task A: Set up data and wait
await agent.utils.job.submitTask(
  "running",
  { preparedData: "value", step: "waiting" },
  false,
  []
);
await agent.utils.setAutomationVariables({ waiting: true });

// Task B: Access Task A's data
const taskA = await agent.utils.job.useAnotherTask();
if (taskA) {
  const taskAData = JSON.parse(taskA.job_proof);
  console.log("Got data from Task A:", taskAData.preparedData);
}

getCurrentTask

Signature
getCurrentTask(): Promise<{ success: false; error: string } | { success: true; parent_task_id: string; job_proof: any, timeout: number }>

Gets information about the currently assigned task, including the parent task ID and job proof data.

Returns { success: true; parent_task_id: string; job_proof: any, timeout: number } | { success: false; error: string }Current task details or error

Example
const task = await agent.utils.job.getCurrentTask();

if (task.success) {
  console.log("Current task ID:", task.parent_task_id);
  const targetUrl = task.job_proof.url;
  const credentials = task.job_proof.credentials;
} else {
  console.log("Error getting task:", task.error);
}

addSubTasks

Signature
addSubTasks(job_variables: JobVariables[], run_immediately?: boolean): Promise<...>

Creates sub-tasks (planned tasks) for the current job or another job owned by the same employer. Each item in job_variables becomes a separate planned task. When job_id is omitted, the current task's job ID is used automatically (and cached). When targeting a different job, the parent task's owner must own or have shared_edit access to the target, and the target must have allow_sub_tasks enabled. Supports three call signatures: positional with JobVariables[], positional with a custom job_id, or a single options object (including remote_device_id).

ParameterTypeDescription
job_variablesJobVariables[] | Record<string, any>[]Array of job variable objects; each becomes the input for one sub-task. Uses JobVariables when targeting the current job, or Record<string, any> when a custom job_id is provided.
run_immediately?booleanWhether to attempt immediate task assignment after creation. Defaults to true.
job_id?stringTarget job ID. If omitted, uses the current task's job ID (fetched once and cached). Different jobs require shared_edit access and allow_sub_tasks enabled.
remote_device_id?stringPin sub-tasks to a specific device by its remote_device_id. Only available via the options object overload.

Returns { success: true; inserted_ids: { planned_task_id: string; input: string }[]; assignment_results?: { planned_task_id: string; assigned: boolean }[] } | { success: false; error: string }Inserted planned task IDs with their inputs, and optional assignment results when run_immediately is true

Create sub-tasks for the current job
const result = await agent.utils.job.addSubTasks([
  { email: "user1@example.com", action: "verify" },
  { email: "user2@example.com", action: "verify" },
]);

if (result.success) {
  const ids = result.inserted_ids.map(t => t.planned_task_id);
}
Create sub-tasks without immediate assignment
const result = await agent.utils.job.addSubTasks(
  [{ url: "https://example.com/page1" }, { url: "https://example.com/page2" }],
  false // Don't assign immediately
);
Create sub-tasks for a different job
const result = await agent.utils.job.addSubTasks(
  [{ targetId: "abc123" }],
  true,
  "674a1b2c3d4e5f6a7b8c9d0e" // Different job ID
);
Options object — pin sub-tasks to a specific device
const result = await agent.utils.job.addSubTasks({
  job_variables: [{ query: "search term 1" }, { query: "search term 2" }],
  run_immediately: true,
  remote_device_id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
});
Options object — all options
const result = await agent.utils.job.addSubTasks({
  job_variables: [{ action: "scrape", url: "https://example.com" }],
  run_immediately: false,
  job_id: "674a1b2c3d4e5f6a7b8c9d0e",
  remote_device_id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
});

getSubTasks

Signature
getSubTasks(planned_task_ids: string[]): Promise<...>

Gets the status and details of sub-tasks by their planned task IDs. Returns a map keyed by planned_task_id. Only returns data for planned tasks whose parent_task_id matches the current task. Status is "planned" if not yet assigned, "deleted" if the job task was removed, or the actual job task status (e.g. "running", "confirmed", "failed") otherwise.

ParameterTypeDescription
planned_task_idsstring[]Array of planned task IDs to query (max 100), from addSubTasks.

Returns { success: true; tasks: Record<string, { parent_task_id, comment, job_proof, timeout, status }> } | { success: false; error: string }Map of planned_task_id to task details. Status is "planned", "deleted", or the job task status.

Check status of sub-tasks
const result = await agent.utils.job.getSubTasks([
  "674a1b2c3d4e5f6a7b8c9d01",
  "674a1b2c3d4e5f6a7b8c9d02",
]);

if (result.success) {
  for (const [plannedTaskId, task] of Object.entries(result.tasks)) {
    console.log(`Task ${plannedTaskId}: status=${task.status}`);
    if (task.status === "confirmed") console.log("Result:", task.job_proof);
  }
}
Poll sub-tasks until all complete
const subTaskResult = await agent.utils.job.addSubTasks([
  { query: "search term 1" },
  { query: "search term 2" },
]);

if (!subTaskResult.success) throw new Error(subTaskResult.error);

const ids = subTaskResult.inserted_ids.map(t => t.planned_task_id);

while (true) {
  const status = await agent.utils.job.getSubTasks(ids);
  if (!status.success) break;

  const allDone = Object.values(status.tasks).every(
    t => ["confirmed", "failed", "declined", "deleted"].includes(t.status)
  );

  if (allDone) break;
  await sleepRandom(5000, 10000);
}

Automation Variables

Accessed via agent.utils (not agent.utils.job), but used for coordinating between job tasks.

setAutomationVariables

Signature
setAutomationVariables(variables: object): Promise<{ success: false; error: string } | { success: true; automation_variables: any }>

Sets automation variables for the current job task to coordinate between tasks in the same job. Set { waiting: true } to make the current task's data available to other tasks via useAnotherTask().

ParameterTypeDescription
variablesobjectVariables to set. Use { waiting: true } to mark this task as available for other tasks.

Returns { success: true; automation_variables: any } | { success: false; error: string }Success status with the stored variables, or error message

Mark task as waiting for another task
await agent.utils.setAutomationVariables({ waiting: true });
// Now another task in the same job can call useAnotherTask()
Store custom variables for task coordination
const result = await agent.utils.setAutomationVariables({
  waiting: true,
  stage: "data_prepared",
  timestamp: Date.now()
});

if (result.success) {
  console.log("Variables set:", result.automation_variables);
} else {
  console.error("Failed to set variables:", result.error);
}

getAutomationVariables

Signature
getAutomationVariables(): Promise<{ success: false; error: string } | { success: true; automation_variables: any }>

Retrieves the automation variables previously set for the current job task. Use this to check the current state of task coordination variables.

Returns { success: true; automation_variables: any } | { success: false; error: string }Success status with the stored variables, or error message

Check current automation variables
const result = await agent.utils.getAutomationVariables();

if (result.success) {
  if (result.automation_variables?.waiting) {
    console.log("This task is marked as waiting");
  }
} else {
  console.error("Failed to get variables:", result.error);
}
Retrieve stored coordination state
const result = await agent.utils.getAutomationVariables();

if (result.success && result.automation_variables) {
  const { stage, timestamp } = result.automation_variables;
  console.log(`Task is at stage: ${stage}, set at: ${timestamp}`);
}