To give your Python AI agent an Android phone, pip install mobilebox and call create_phone(): it returns a cloud Android phone that is ready to use. Your agent reads its screen as numbered elements, taps, types, installs your build and takes screenshots, and your code deletes the phone when the run ends.

One phone per pull request

Give every pull request its own phone. Start it, install the build that pull request produced, walk the flow a reviewer would click through, screenshot each step, delete the phone. Nothing carries over from the last run, and nothing keeps running when a check fails. Park the phone instead of deleting it when the next run should start with the app still logged in.

Install

bash
pip install mobilebox
export MOBILESANDBOX_API_KEY=...

The package is on PyPI: Python 3.10 or newer, no other dependencies. Create the key in the dashboard, or paste one line into your agent and let it get its own through setup.md.

The script

python
# pr_check.py: one phone per pull request. Install the build, walk the flow, screenshot each step.
#   pip install mobilebox
#   MOBILESANDBOX_API_KEY=... python pr_check.py app.apk org.fossify.math
import sys

from mobilebox import Mobilebox

apk, package = sys.argv[1], sys.argv[2]
FLOW = [  # each step: its actions, then the text that proves it worked
    ("open", [{"type": "open_app", "package": package}], "="),
    ("multiply", [{"type": "tap", "target": {"text": key}} for key in ("6", "×", "7", "=")], "42"),
]

mb = Mobilebox()  # reads MOBILESANDBOX_API_KEY
phone = mb.create_phone(name="pr-check", idle_timeout=120, max_duration=600)
try:
    app = mb.install_app(phone.id, file=apk)
    print(f"installed {app.package} {app.version_name} on {phone.id}")
    for step, actions, expect in FLOW:
        result = mb.act(phone.id, actions + [{"type": "wait_for", "text": expect}])
        with open(f"{step}.png", "wb") as f:
            f.write(mb.screenshot(phone.id))  # the evidence, also when the step failed
        if not result.ok:
            sys.exit(f"{step} failed: {result.error}\n{result.screen.text}")
        print(f"{step}: ok, {step}.png")
finally:
    mb.delete_phone(phone.id)  # nothing keeps running or billing

Each step in FLOW is a batch of actions and the text that proves it worked. One act call runs the whole batch and stops at the first failure; the closing wait_for waits for the text to appear. The screenshot comes before the check, so a failed step still leaves its picture. sys.exit inside try still runs finally, so the phone is deleted either way.

What it printed

We ran it on production on November 10, 2026 with Fossify Calculator 1.4.0 from F-Droid as the build:

text
installed org.fossify.math 1.4.0 on ph_7g3zojioh2ow
open: ok, open.png
multiply: ok, multiply.png

25.6 seconds from create to delete, boot included. Then we broke the check on purpose, expecting 43:

text
multiply failed: wait_timeout: "43" did not appear within 10000 ms. Next: Observe the screen to see what is there instead.
app: org.fossify.math
[4] Text "6×7" (540,327)
[5] Text "42" (540,651)

Shortened to the two lines that matter. Exit code 1, the phone deleted, and the screen text says what was there instead. In CI, run the script after your build step with the key as a secret and upload the PNGs as artifacts; the APK smoke test guide has the GitHub Actions side.

Let the model walk the flow

A script knows its steps. When the flow changes with every pull request, hand the walk to a model: pip install langchain-mobilebox gives a LangChain or LangGraph agent the phone as tools. Keep create, install, screenshots and delete in your code, and give the agent MobileboxObserve and MobileboxAct for the phone you made, with a task like "walk the sign-up flow and say where it breaks". The whole program is on the LangGraph page; it answered in 34 seconds on production.

What a run costs

A phone costs $0.01 a minute while it is ready, billed per second with a one-minute minimum; boot time is free. Both runs above were ready for under a minute, so each cost 1 cent. A model walking a sign-up flow for 3 minutes costs 3 cents of phone time plus your model’s tokens, and 100 pull requests a month at that pace cost $3 in phones. The quickstart and the Python client reference cover the rest.