agent.utils.job
Manage job tasks, submit results, and request new tasks. Accessed through agent.utils.job.
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
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.
| Parameter | Type | Description |
|---|---|---|
automationStatus | "running" | "success" | "failed" | "declined" | Current status of the task |
data | Record<string, any> | Task result data as key-value pairs |
finish | boolean | Whether 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
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");
}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 || "" }]
);// files parameter is ignored when finish=false
await agent.utils.job.submitTask(
"running",
{ currentStep: 3, totalSteps: 10 },
false,
[]
);await agent.utils.job.submitTask(
"declined",
{ reason: "Item out of stock" },
true,
[]
);submitTaskToAnotherJob
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).
| Parameter | Type | Description |
|---|---|---|
job_id | string | ID of the target data-dump job (devices_automation, automation_id set, no planned tasks). |
data | Record<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.
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);
}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 || "" }],
);await agent.utils.job.submitTaskToAnotherJob(
"68868530c189957861cd698a",
{ reason: "captcha blocked" },
"failed",
);useAnotherTask
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 } | null — Task details from another waiting task, or null if none available
// 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");
}// 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
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
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
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).
| Parameter | Type | Description |
|---|---|---|
job_variables | JobVariables[] | 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? | boolean | Whether to attempt immediate task assignment after creation. Defaults to true. |
job_id? | string | Target 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? | string | Pin 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
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);
}const result = await agent.utils.job.addSubTasks(
[{ url: "https://example.com/page1" }, { url: "https://example.com/page2" }],
false // Don't assign immediately
);const result = await agent.utils.job.addSubTasks(
[{ targetId: "abc123" }],
true,
"674a1b2c3d4e5f6a7b8c9d0e" // Different job ID
);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",
});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
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.
| Parameter | Type | Description |
|---|---|---|
planned_task_ids | string[] | 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.
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);
}
}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
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().
| Parameter | Type | Description |
|---|---|---|
variables | object | Variables 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
await agent.utils.setAutomationVariables({ waiting: true });
// Now another task in the same job can call useAnotherTask()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
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
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);
}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}`);
}