Skip to main content
The agent37-android template is an Android phone your code can drive: the Android 14 emulator, the SDK, ADB, and a live view of the screen in the browser, already installed and already running. It is a web app and a device, not an agent harness: there is no chat API on this instance. It only runs as a VM instance. The emulator needs hardware virtualization (/dev/kvm), which a VM has and a sandbox does not, so a create without "type": "vm" is a 400.
Paste this into your coding agent

Create one

curl
4 vCPU / 8 GB is the smallest shape the emulator is comfortable on, and 20 GB of disk leaves the phone’s own storage room to grow. A funded workspace is required, as for every VM instance. The create returns as soon as the machine has started. Android is still booting at that point: the phone is created on the first boot, so the first one takes a few minutes and every boot after it loads the emulator’s quick-boot snapshot instead. Wait for it with the image’s own helper, which blocks until Android reports sys.boot_completed:
curl

Drive it with ADB

ADB is already connected to the phone, so exec is all you need. Nothing has to be exposed to the internet for your code to drive the device.
curl
The commands a device-driving agent leans on: SSH works too, and is the better way in when you want adb pull of something big or an interactive shell: ssh root@ab12cd34ef.agent37.app.

Watch the screen

The screen is served on port 6901 by noVNC, so any browser can open it with no plugin and no client. Mint a signed URL and point it at noVNC’s own page:
curl
Keep the token and change the path to /vnc.html:
Add &view_only=1 to watch without touching. The URL is a credential: anyone holding it can tap and type on the phone, so mint a short one and hand it only to the device’s owner. To embed the screen in your own app rather than open a tab, mount the noVNC client in your page and connect its WebSocket straight to the instance; Hermes with a desktop has the code, and it applies here unchanged. noVNC is what the template ships because it needs nothing installed and rides the same authenticated edge as every other port. For a smoother picture, run ws-scrcpy on the instance and serve it on its own port: it streams H.264 over a WebSocket and the browser decodes it with WebCodecs. The native scrcpy client is better still, over an SSH tunnel to ADB (agent37 ssh ab12cd34ef -- -L 5037:localhost:5037). The emulator’s own WebRTC stream needs UDP, which the Agent37 edge does not carry.

What is on the image

google_apis carries Google Play services, so sign-in and push work, and it keeps adb root. It does not include the Play Store app: sideload with adb install, or build your own image on system-images;android-34;google_apis_playstore;x86_64 if you need the store itself. The same applies to another Android version: sdkmanager --install "system-images;android-16;google_apis;x86_64" on the instance, or bake it into your own template. What the phone stores (apps, logins, files, the quick-boot snapshot) lives in the AVD on the instance’s persistent disk, so it survives stop, start, restart, resize and image updates. The SDK itself is in the image and costs nothing against your disk. Environment knobs, as instance env: ANDROID_AVD_RAM_MB (default 2048), ANDROID_AVD_DATA_MB (the phone’s storage, default 6144), ANDROID_AVD_DEVICE (default pixel_6), ANDROID_SCREEN_GEOMETRY (default 560x1000x24, sized to the window the emulator draws) and ANDROID_EMULATOR_ARGS for anything else you want to pass the emulator.

Leave auto-sleep off

The emulator is the one workload that has to stay awake. It uses hardware virtualization itself, and after a wake the first call into /dev/kvm fails and takes the emulator down with it. Auto-sleep is off unless you ask for it, so there is nothing to do but leave it off; restart brings the phone back. Use stop and start to park a phone instead: that releases the compute charge and cold-boots cleanly.