start_run creates the run, holds its state machine, meters it, and hands you a
vrxBaseUrl. Nothing then drives the device until a program of yours picks that
url up and starts asking for frames. If you never point a worker at it, the run
sits in queued until its deadline passes and it ends as failed.
This page exists because that is easy to miss. Read it before you write your
first start_run call.
Who does what
The split is deliberate. The control plane is hands and eyes. The judgment about
what to tap next is yours, which is what lets you choose your own model, your
own prompt, and your own stopping rule, and change any of them without waiting
for us.
If you do not want to write one
You do not have to use the agent tier at all. The low level tools drive a device directly and need no worker:acquire_deviceto take a lease.screenshotto see the screen.tap,swipe,type_textto act.release_devicewhen you are done.
What a worker has to do
A worker repeats four steps until it is finished:- Ask for a frame.
- Decide what to do, usually by sending the frame to a vision capable model.
- Send one action.
- Report the outcome when it is done or stuck.
vrxBaseUrl,
and it needs nothing else: no API key, no lease id, no headers. If your worker
wants any of those, it has drifted outside the contract.
The contract in full
Everything a worker may call, rooted at thevrxBaseUrl you were handed:
Because
GET /devices tells your worker which device it is bound to, the
vrxBaseUrl really is the only input it needs.
Action payloads, exactly as the channel accepts them:
screenmust match the frame you just received. It is checked against the current frame, not trusted. Measure the image bytes you were served rather than assuming a device resolution, and re-measure after every frame. A mismatch is refused with a400telling you to re-observe.- Coordinates are integers in that frame’s own pixels, and
coordinate_spacemust be the stringscreenshot_pixels. Taps and swipes need both fields.type_text,press_buttonandopen_appdo not. - Take a frame before your first action. Acting without ever having observed is refused. There is no coordinate basis yet, so there is nothing to bind the action to.
type_texttakes at most 4096 characters, the same ceiling the MCPtype_texttool publishes. Longer text is refused with a400, not cut.duration_mson a swipe is a positive integer. Zero, a fraction or a string is refused rather than read as the default. A value above the contract’s ceiling is performed at the ceiling, because the upstream driver sends very large values for a drag.
press_button accepts home, back, enter, delete, app_switch, power,
volume_up and volume_down. Not every device does all of them: the
capabilities.press_button field on GET /devices tells you which ones this
device advertises, and one it does not support is refused with a 409.
Report exactly one of three states when you stop:
The loop, in about thirty lines
This is the shape, not a product. Fill indecide with a call to the vision
capable model of your choice, and read Device surface
codes for the refusals you have to handle.
Choosing a model
Any model that reads an image and returns a coordinate will work. The quality of a run is mostly the quality of this decision, so start with the strongest vision capable model you have access to and reduce only if you measure that a smaller one holds up. Your worker pays for its own model calls. phonebase meters frames, not tokens. One frame is one step no matter how many times you reason over it, so a worker that thinks twice about the same frame costs you model tokens and costs nothing extra here. See Metering units.How to tell your worker never connected
The run tells you.GET /v1/runs/{runId} and get_run both return
workerFirstContactAt:
nullmeans no worker has reached this run. Aqueuedrun withnullhere is waiting for you, not for us.- A timestamp means a worker arrived, and
stepSeqtells you how many frames it has taken since.
failed with reason deadline_exceeded, detail says which
of the two happened: nobody connected, or a worker connected and did not finish.
See Runs.