Workflow Examples
These examples cover the workflows readers are most likely to need first: connect to a device, open an app, inspect the screen, act, wait, verify, recover from common UI issues, and collect evidence.
Assumptions:
- You are in the repository root.
- Android Emu Agent is installed with
uv sync --all-extras. - The daemon can reach an emulator or device.
com.example.appis the target package../artifacts/is local scratch space and is ignored by git.
Replace placeholders such as <session-id>, <device-serial>, and <apk-path> before running a
command.
Connect to a Device and Start a Session
Use this flow at the start of an automation run.
Confirm that the Android SDK can see a target:
adb devices
uv run android-emu-agent device list
Optional: boot an emulator if no target is running:
uv run android-emu-agent emulator list-avds
uv run android-emu-agent emulator start <avd-name> --wait-boot
Start the daemon and check its status:
uv run android-emu-agent daemon start
uv run android-emu-agent daemon status --json
Start a session:
uv run android-emu-agent session start --device <device-serial> --json
Verify that the response includes status: done and session_id.
Install or Reset an App Before Testing
Use this flow when a run must start from a known app state.
Install or replace the APK:
uv run android-emu-agent app install <apk-path> --session <session-id> --grant-permissions --json
Optional: clear app data:
uv run android-emu-agent app reset <session-id> com.example.app
Launch the app:
uv run android-emu-agent app launch <session-id> com.example.app
uv run android-emu-agent wait idle <session-id> --timeout-ms 5000
Verify the foreground app:
uv run android-emu-agent expect current-app <session-id> --package com.example.app
If installation fails, check that the target allows APK installs and that <apk-path> points to a
local APK file.
Inspect a Screen and Tap a Control
Use this flow for the normal observe, act, verify loop.
Capture a compact text snapshot:
uv run android-emu-agent ui snapshot <session-id> --format text
Tap a ref from the snapshot:
uv run android-emu-agent action tap <session-id> ^a1
Verify the new screen:
uv run android-emu-agent ui snapshot <session-id> --format text
If the target should be reusable across app versions, prefer a semantic selector:
uv run android-emu-agent action tap <session-id> 'text:"Sign in" || id:com.example:id/sign_in'
Fill a Form
Use refs from a fresh snapshot for text fields. This avoids typing into the wrong field after the UI changes.
Launch the screen and wait for it to settle:
uv run android-emu-agent app launch <session-id> com.example.app
uv run android-emu-agent wait idle <session-id> --timeout-ms 5000
uv run android-emu-agent ui snapshot <session-id> --format text
Set text on the email and password fields:
uv run android-emu-agent action set-text <session-id> ^a2 "agent@example.com"
uv run android-emu-agent action set-text <session-id> ^a3 "test-password"
Submit and verify the next state:
uv run android-emu-agent action tap <session-id> ^a4
uv run android-emu-agent expect exists <session-id> --text "Welcome" --timeout-ms 10000
If the keyboard blocks the submit button, dismiss it before tapping:
uv run android-emu-agent action back <session-id>
uv run android-emu-agent wait idle <session-id> --timeout-ms 3000
Wait for Navigation or Loading State
Use waits instead of fixed sleeps. Wait commands return structured timeout errors when the expected state does not appear.
uv run android-emu-agent action tap <session-id> 'text:"Checkout" || id:com.example:id/checkout'
uv run android-emu-agent wait gone <session-id> --text "Loading" --timeout-ms 10000
uv run android-emu-agent wait exists <session-id> --text "Payment" --timeout-ms 10000
uv run android-emu-agent expect activity <session-id> CheckoutActivity --timeout-ms 5000
If the wait times out, capture a fresh snapshot and check whether the app navigated to a different state than expected.
Recover When an Element Is Missing
Use this flow after ERR_NOT_FOUND, ERR_STALE_REF, or a snapshot that does not show the target.
Wait for the UI to settle:
uv run android-emu-agent wait idle <session-id> --timeout-ms 3000
Capture a full snapshot once:
uv run android-emu-agent ui snapshot <session-id> --full --format text
Inspect selector capability support:
uv run android-emu-agent device capabilities --session <session-id> --json
Retry with a semantic selector:
uv run android-emu-agent action tap <session-id> 'text-contains:"Continue" enabled:true clickable:true'
If no selector is reliable, capture a screenshot before using coordinates:
uv run android-emu-agent ui screenshot <session-id> --pull --output ./artifacts/missing-target.png
uv run android-emu-agent action tap <session-id> coords:540,1820
Use coordinates as the last resort because they are sensitive to device size, orientation, font scale, and layout changes.
Handle Permission and System Setup
Use this flow when an app needs notification, camera, location, or other runtime permission setup before a test.
List requested and granted permissions:
uv run android-emu-agent system permissions list com.example.app --session <session-id> --json
Grant a runtime permission:
uv run android-emu-agent system permissions grant com.example.app android.permission.POST_NOTIFICATIONS --session <session-id> --json
Optional: open Android system surfaces for manual or agent inspection:
uv run android-emu-agent system notifications open --session <session-id>
uv run android-emu-agent system quick-settings open --session <session-id>
Permission changes still follow Android runtime permission rules. If a permission cannot be granted, check the app manifest, Android version, and device policy.
Run a Reusable Task Script
Use a .aea script when a flow should be checked in, reviewed, and repeated.
Validate the script without touching a device:
uv run android-emu-agent task validate examples/tasks/checkout-smoke.aea
Run it against the active session:
uv run android-emu-agent task run examples/tasks/checkout-smoke.aea --session <session-id> --json
If it fails, inspect the failure payload and preserve evidence:
uv run android-emu-agent artifact save-snapshot <session-id> --json
uv run android-emu-agent artifact screenshot <session-id> --pull --output ./artifacts/task-failure.png --json
For writing task scripts, use the task script guide. For exact grammar, use the
.aea specification.
Collect Evidence After a Failed Flow
Use this sequence after a failed action, failed expectation, crash, or confusing UI state. It collects bounded evidence without changing app state further.
Save the latest structured UI state:
uv run android-emu-agent artifact save-snapshot <session-id> --json
Capture a screenshot:
uv run android-emu-agent artifact screenshot <session-id> --pull --output ./artifacts/failure-screen.png --json
Pull focused logs from the last few minutes:
uv run android-emu-agent artifact logs \
--session <session-id> \
--app com.example.app \
--type errors \
--since "10m ago" \
--json
Add current app and task context:
uv run android-emu-agent app current --session <session-id> --json
uv run android-emu-agent app task-stack --session <session-id> --json
Create one bundle with available evidence:
uv run android-emu-agent artifact bundle <session-id> --json
If the failure looks like a crash or ANR, add reliability data:
uv run android-emu-agent reliability profile com.example.app --session <session-id> --json
uv run android-emu-agent reliability exit-info com.example.app --session <session-id> --json
Record a Trace for a Flaky Flow
Use traces when a flow fails intermittently and you need replayable daemon request/response evidence. Replay is a dry-run plan, so inspecting a trace does not mutate a device.
uv run android-emu-agent trace start <session-id> --label checkout-flake
uv run android-emu-agent ui snapshot <session-id> --format text
uv run android-emu-agent action tap <session-id> 'text:"Checkout" || id:com.example:id/checkout'
uv run android-emu-agent wait exists <session-id> --text "Payment" --timeout-ms 5000
uv run android-emu-agent trace stop <session-id> --output ./artifacts/checkout-flake.aea-trace.zip
uv run android-emu-agent trace replay ./artifacts/checkout-flake.aea-trace.zip --until-failure
uv run android-emu-agent trace export ./artifacts/checkout-flake.aea-trace.zip --output ./artifacts/checkout-flake.md
Attach the .aea-trace.zip, exported Markdown, and any screenshots or logs collected during the
same run.
Use Visual Grounding for Screenshot Review
Use visual grounding when text output is not enough and a human or vision model needs screenshot coordinates for selected refs. Grounding uses the latest snapshot; it does not run OCR or image matching.
uv run android-emu-agent ui snapshot <session-id> --format text
uv run android-emu-agent ui ground <session-id> --ref ^a1 --ref ^a4 --pull --output ./artifacts/grounding.json --json
uv run android-emu-agent ui screenshot <session-id> --pull --output ./artifacts/screen.png --json
Verify that grounding.json includes coordinate_space, screenshot_path, ref, bounds, and
center fields for the selected refs.
Preflight an Intent or Deep Link
Use resolve-intent before launching an implicit intent or deep link on a device that may have
multiple handlers.
uv run android-emu-agent app resolve-intent \
--session <session-id> \
--action android.intent.action.VIEW \
--data "https://example.com/deep" \
--json
uv run android-emu-agent app deeplink <session-id> "https://example.com/deep"
uv run android-emu-agent wait activity <session-id> DeepLinkActivity --timeout-ms 10000
If the preflight is ambiguous, launch with an explicit package or component:
uv run android-emu-agent app intent <session-id> \
--action android.intent.action.VIEW \
--data "https://example.com/deep" \
--package com.example.app
Use --component com.example.app/.DeepLinkActivity when you know the exact activity and want to
avoid resolver choice entirely.
Attach a Debugger at Startup
Use this flow when UI-level signals are not enough and the target app is debuggable.
uv run android-emu-agent app launch <session-id> com.example.app --wait-debugger
uv run android-emu-agent debug attach --session <session-id> --package com.example.app --keep-suspended
uv run android-emu-agent debug break set com.example.app.MainActivity 42 --session <session-id>
uv run android-emu-agent debug resume --session <session-id>
uv run android-emu-agent debug events --session <session-id>
uv run android-emu-agent debug observe --session <session-id> --json
uv run android-emu-agent debug detach --session <session-id>
Debugger commands require JDK 17+ and a debuggable app. Use --process on debug attach when the
package has multiple debuggable processes.