Step Tracking & Debugging
UtilsTrack automation progress and debug failures
Access step tracking through agent.utils.outOfSteps. Used for tracking automation progress and debugging when automations run out of steps or timeout.
interface OutOfStepsUtils { storeScreen( screen: AndroidNode, stage: string, screenState: string, remainingSteps: number, screenshotRecord: ScreenshotRecord ): Promise<void>;
submit( type: "outOfSteps" | "timeout" | "debug", tag?: string, fromDisk?: boolean ): Promise<{ success: false; error: string } | { success: true; id: string }>;
enableDiskStorage(options?: { maxBytes?: number }): Promise< { success: false; error: string } | { success: true; directory: string; maxBytes: number } >;}Stored screens are kept in sessionStorage, which only holds a few MB, so older screens are trimmed early. Call enableDiskStorage() to also keep them on disk, then pass fromDisk: true to submit to send the longer disk history.
storeScreen()
storeScreen(screen: AndroidNode, stage: string, screenState: string, remainingSteps: number, screenshotRecord: ScreenshotRecord): Promise<void>Stores the current screen state for debugging purposes. Call this periodically during automation to track progress and help diagnose issues when automations fail.
Parameters
| Name | Type | Description |
|---|---|---|
screen | AndroidNode | The current screen content from screenContent() |
stage | string | Current stage/phase of the automation (e.g., 'login', 'checkout') |
screenState | string | Description of the current screen state |
remainingSteps | number | Number of steps remaining in the automation |
screenshotRecord | ScreenshotRecord | Screenshot quality setting |
Examples
const screen = await agent.actions.screenContent();
// Store screen state for debuggingawait agent.utils.outOfSteps.storeScreen( screen, "login", "waiting_for_credentials", 50, ScreenshotRecord.LOW_QUALITY);submit()
submit(type: "outOfSteps" | "timeout" | "debug", tag?: string, fromDisk?: boolean): Promise<{ success: false; error: string } | { success: true; id: string }>Submits the collected screen states for analysis. Call this when the automation ends unexpectedly or for debugging. The server keeps the 200 most recent records per type per automation — except "debug" records, which are kept per tag: each tag retains its own 200 most recent records.
Parameters
| Name | Type | Description |
|---|---|---|
type | "outOfSteps" | "timeout" | "debug" | Reason for submission |
tag | string | Optional tag for "debug" submissions (defaults to "default", max 64 characters). Use distinct tags to keep separate debug histories — the server retains 200 debug records per tag. Ignored for non-debug submissions. |
fromDisk? | boolean | When true, sends the screens stored on disk instead of the ones in sessionStorage. Returns an error if enableDiskStorage() hasn't been called. Pass undefined as the tag for a non-debug submission.(default: false) |
Returns
{ success: true; id: string } | { success: false; error: string }Result with submission ID on success or error message on failure
Examples
const result = await agent.utils.outOfSteps.submit("timeout");if (result.success) { console.log("Debug data submitted with ID:", result.id);} else { console.log("Failed to submit:", result.error);}// Collect screens during automationawait agent.utils.outOfSteps.storeScreen(screen1, "step1", "initial", 100, ScreenshotRecord.HIGH_QUALITY);await agent.utils.outOfSteps.storeScreen(screen2, "step2", "processing", 80, ScreenshotRecord.LOW_QUALITY);
// Submit for analysis (stored under the "default" tag)await agent.utils.outOfSteps.submit("debug");// Each tag keeps its own history of 200 records,// so tagged submissions don't push out other debug dataawait agent.utils.outOfSteps.submit("debug", "login-flow");// Needs enableDiskStorage() earlier in the runawait agent.utils.outOfSteps.submit("outOfSteps", undefined, true);enableDiskStorage()
enableDiskStorage(options?: { maxBytes?: number }): Promise<{ success: false; error: string } | { success: true; directory: string; maxBytes: number }>Also stores screens (UI hierarchy and screenshot) on disk, which keeps a much longer history than sessionStorage. Screens are still stored in sessionStorage as before, and submit sends that copy unless you pass fromDisk: true. Call it once, before the first storeScreen; screens stored before the call are only in sessionStorage. Each screen is gzipped and encrypted with AES-GCM, using a key that only exists in memory for the current run, and written as a hidden file in the device's Downloads folder. The oldest disk screens are trimmed when they exceed maxBytes, or when a write fails because the disk is full; a screen that can't be written to disk is only in sessionStorage. Screens are kept after submit, so later submissions still include them. The run's disk screens are deleted once agent.utils.job.submitTask succeeds with finish set to true (the default), whatever the status, so call outOfSteps.submit(type, tag, true) before that. Stored files older than one day, for example ones left by a run that crashed, are deleted when an automation starts. Calling it again only updates maxBytes. Needs app version 2.138 (150) or newer.
Parameters
| Name | Type | Description |
|---|---|---|
options.maxBytes? | number | Budget for stored screens, measured as the size of their JSON. Values are clamped to 1–90 MB; 90 MB is also the most one submission sends.(default: 94371840 (90 MB)) |
Returns
{ success: true; directory: string; maxBytes: number } | { success: false; error: string }The directory used and the effective budget, or why disk storage could not be enabled (screens then stay in sessionStorage)
Examples
const storage = await agent.utils.outOfSteps.enableDiskStorage();if (!storage.success) { console.warn("Disk storage unavailable:", storage.error);}
// storeScreen is used exactly as before; screens go to sessionStorage and diskawait agent.utils.outOfSteps.storeScreen(screen, "login", "form", 50, ScreenshotRecord.HIGH_QUALITY);
// Send the disk history (falls back to sessionStorage if disk storage is off)await agent.utils.outOfSteps.submit("outOfSteps", undefined, storage.success);await agent.utils.outOfSteps.enableDiskStorage({ maxBytes: 30 * 1024 * 1024 });Supporting Types
ScreenshotRecord
Enum for screenshot quality settings.
enum ScreenshotRecord { HIGH_QUALITY, // Full quality screenshot LOW_QUALITY, // Compressed screenshot (faster, smaller) NONE // No screenshot}Usage Pattern
async function runAutomation() { let remainingSteps = 100;
while (remainingSteps > 0) { const screen = await agent.actions.screenContent();
// Store screen state periodically await agent.utils.outOfSteps.storeScreen( screen, getCurrentStage(), describeScreen(screen), remainingSteps, ScreenshotRecord.LOW_QUALITY );
// Perform automation step const result = await performStep(screen); if (!result.success) { // Submit debug data on failure await agent.utils.outOfSteps.submit("outOfSteps"); throw new Error("Automation failed"); }
remainingSteps--; }
// Submit on timeout if loop exits without success await agent.utils.outOfSteps.submit("timeout");}