Automation API

Android device automation

Task Submission

Submit results, collect data, and handle job tasks

Job tasks allow your automation to process multiple items (accounts, orders, etc.) in sequence. You can submit results, collect data, and request new tasks.

Job Task Overview

Access job task methods through agent.utils.job:

TypeScript
agent.utils.job = {
submitTask(status, data, finish, files): Promise<TaskResult>;
useAnotherTask(): Promise<TaskInfo | null>;
getCurrentTask(): Promise<CurrentTaskResult>;
}

Submitting Task Results

Use submitTask() to report progress or complete a task:

submitTask Parameters
TypeScript
await agent.utils.job.submitTask(
status, // "running" | "success" | "failed" | "declined"
data, // Record<string, any> - data to store
finish?, // boolean - true to complete the task (default: true)
files? // File[] - files to upload (default: [])
);
// Important notes:
// - Once finish=true is passed, you cannot submit again for the same task
// - The files parameter is ignored when finish=false

Status Values

StatusDescriptionFinish?
"running"Task is in progress, reporting intermediate datafalse
"success"Task completed successfullytrue
"failed"Task failed (error, blocked, etc.)true
"declined"Task was declined (invalid data, etc.)true

Reporting Progress

Progress updates
TypeScript
// Report progress without finishing
// Note: files parameter is ignored when finish=false
await agent.utils.job.submitTask(
"running",
{
stage: "login",
progress: 25,
timestamp: Date.now()
},
false // Don't finish - must specify when not finishing!
);
// Later, report more progress
await agent.utils.job.submitTask(
"running",
{
stage: "processing",
progress: 75,
itemsProcessed: 10
},
false // Must be false for progress updates
);

Completing Tasks

Success and failure
TypeScript
// Complete with success (files and finish default to [] and true)
await agent.utils.job.submitTask("success", {
email: "user@example.com",
orderId: "12345",
completedAt: new Date().toISOString(),
itemsProcessed: 15
});
// Don't forget to stop the automation!
stopCurrentAutomation();
// Complete with failure
await agent.utils.job.submitTask("failed", {
email: "user@example.com",
error: "Account locked",
stage: "login",
failedAt: new Date().toISOString()
});
stopCurrentAutomation();

File Attachments

Attach files (screenshots, logs, etc.) to task submissions:

Submitting with files
TypeScript
// Collect files during automation
const files: { name: string; extension: string; base64Data: string }[] = [];
// Take a screenshot
const screenshot = await agent.actions.screenshot(1080, 1920, 80);
files.push({
name: "final_screen",
extension: "jpg",
base64Data: screenshot.base64
});
// Submit with files (finish defaults to true)
await agent.utils.job.submitTask(
"success",
{ email: "user@example.com", orderPlaced: true },
true, // Final submission
files // Pass files array
);
stopCurrentAutomation();

Getting Current Task

Get information about the current job task:

getCurrentTask
TypeScript
const task = await agent.utils.job.getCurrentTask();
if (task.success) {
// Task data is available
const { job_proof, ...otherData } = task;
console.log("Job proof:", job_proof);
// Job variables are also available
const { email, password } = agent.arguments.jobVariables;
// Process the task...
} else {
console.log("No task available or error:", task.error);
}

Data Collection Pattern

A common pattern for collecting and submitting data throughout the automation:

Data collection
TypeScript
// Global data object
const collectedData: Record<string, any> = {
startedAt: new Date().toISOString(),
stages: [],
errors: [],
metrics: {
screensProcessed: 0,
actionsPerformed: 0
}
};
function recordStage(stage: string, data?: object) {
collectedData.stages.push({
stage,
timestamp: Date.now(),
...data
});
}
function recordError(error: string, context?: object) {
collectedData.errors.push({
error,
timestamp: Date.now(),
...context
});
}
function recordMetric(metric: string, value: number) {
collectedData.metrics[metric] = (collectedData.metrics[metric] || 0) + value;
}
// Usage during automation
recordStage("login_started");
recordMetric("screensProcessed", 1);
// Submit progress (files ignored when finish=false)
await agent.utils.job.submitTask(
"running",
{ ...collectedData, currentStage: "login" },
false // Don't finish for progress updates
);
// Submit final
collectedData.completedAt = new Date().toISOString();
await agent.utils.job.submitTask("success", collectedData);
// Always stop the automation when done
stopCurrentAutomation();

Error Handling

Robust task handling
TypeScript
async function runTask() {
const files: File[] = [];
try {
// Get task info
const task = await agent.utils.job.getCurrentTask();
if (!task.success) {
throw new Error("No task available");
}
// Process...
const result = await processAutomation();
// Success
await agent.utils.job.submitTask("success", result, true, files);
} catch (error) {
console.error("Task failed:", error);
// Take failure screenshot
try {
const screenshot = await agent.actions.screenshot(1080, 1920, 80);
files.push({
name: "error_screen",
extension: "jpg",
base64Data: screenshot.base64
});
} catch (e) {
// Ignore screenshot errors
}
// Determine failure type
const errorMessage = String(error);
let status: "failed" | "declined" = "failed";
if (errorMessage.includes("invalid") ||
errorMessage.includes("not found")) {
status = "declined"; // Invalid input data
}
// Submit failure
await agent.utils.job.submitTask(status, {
error: errorMessage,
stage: currentStage,
timestamp: Date.now()
}, true, files);
} finally {
// Always stop the automation
stopCurrentAutomation();
}
}

Best Practices

Report Progress Regularly

Submit "running" status on stage changes. This shows progress in the dashboard and helps with debugging.

Include Useful Data

Include timestamps, stage info, and any data that helps understand what happened. This is invaluable for debugging failed tasks.

Attach Screenshots on Failure

When a task fails, try to capture a screenshot of the current screen. This makes it much easier to understand what went wrong.

Use "declined" for Invalid Data

Use "declined" status when the task data is invalid (wrong credentials, account not found, etc.). Use "failed" for actual errors.

Next Steps