# An Android phone for your Python AI agent

pip install mobilebox, then one cloud phone per pull request: start it, install the build, walk the flow, screenshot each step, delete it. A tested script, the LangGraph version and what a run costs.

Guides4 min read

In this article

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](https://mobilebox.dev/blog/park-resume-android).

## Install

```
pip install mobilebox
export MOBILESANDBOX_API_KEY=...
```

The package is on [PyPI](https://pypi.org/project/mobilebox/): Python 3.10 or newer, no other dependencies. Create the key in the [dashboard](https://mobilebox.dev/dashboard), or paste one line into your agent and let it get its own through [setup.md](https://mobilebox.dev/setup.md).

## The script

```
# 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](https://f-droid.org/packages/org.fossify.math/) 1.4.0 from F-Droid as the build:

```
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`:

```
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](https://mobilebox.dev/blog/android-apk-ci-smoke-tests) 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](https://mobilebox.dev/integrations/langgraph); 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](https://mobilebox.dev/docs#use-python) and the [Python client reference](https://mobilebox.dev/docs/reference#python-client) cover the rest.

## Try it in your agent in 60 seconds

Paste this into Claude Code, Cursor, Codex or any agent that can read a web page. It asks for your email, gets its own key at once and adds the phone tools; the 6-digit code from your inbox keeps the workspace.

```
Set up Mobilebox for me: read https://mobilebox.dev/setup.md?via=android-phone-for-python-ai-agent and follow it.
```

[What your agent reads](https://mobilebox.dev/setup.md?via=android-phone-for-python-ai-agent)

In this article

[All articles](https://mobilebox.dev/blog)

## Next questions

- [Mobilebox or Firebase Test Lab?](https://mobilebox.dev/blog/mobilebox-vs-firebase-test-lab?via=next-firebase)

- [Mobilebox or BrowserStack?](https://mobilebox.dev/blog/mobilebox-vs-browserstack?via=next-browserstack)

- [Cloud phone or a local emulator?](https://mobilebox.dev/blog/mobilebox-vs-local-emulator?via=next-emulator)

- [Mobilebox, Limrun or Mobilerun?](https://mobilebox.dev/blog/mobilebox-vs-limrun?via=next-limrun)

- [How do I add it to Cursor, Codex or VS Code?](https://mobilebox.dev/blog/android-mcp-cursor-codex-vscode?via=next-setup)

- [Can my agent run 50 phones in parallel?](https://mobilebox.dev/blog/run-android-phones-in-parallel?via=next-parallel)

- [Can my agent use an iPhone?](https://mobilebox.dev/ios?via=next-iphone)

- [Can each phone get a residential IP?](https://mobilebox.dev/blog/residential-ip-per-phone?via=next-residential-ip)
