//Guide
Run one workflow on many phones at once
Once a script works on one phone, save it in Axilio as a workflow and run it on as many of your dedicated phones as you need, from one request. Each run gets its own phone session, recording and step-by-step trace.
Use it to finish a batch sooner by splitting it across phones, or to run the same job with different inputs side by side. You queue runs from the dashboard, the CLI, Python, Go or REST.
Updated October 6, 2026.
Workflows and runs
A workflow is the code. A run is one execution of it on one phone.
1.0The modelWorkflow
Your Python, saved in Axilio in numbered revisions. Axilio runs it unchanged, on whichever phone each run gets.
Run
One execution of the workflow on one phone. Its run ID is also the ID of the phone session it creates.
Your phones
Pin each run to one of your dedicated phones. A run that can't start yet waits in the queue until a phone is free.
Save the workflow
Write the steps once, then save them as revision 1 of a named workflow.
2.0Step 1cat > workflow.py <<'PY'# From the home screen: open Chrome, then search.driver.locator(query="the Chrome app icon").tap()driver.locator(query="the address bar").fill("axilio")driver.key_press(Key.ENTER)PYaxilio workflows create search-flow --platform android --code workflow.py
driver is ready for you
Axilio binds driver and Key to the phone each run gets, so the source never allocates a phone of its own.
Every save is a revision
Pull, edit and push the code as new revisions. Restoring an old one copies it forward, so history is never lost.
Recording and traces are on
Runs are recorded and traced by default. Turn either off for every run with --recording=false or --telemetry=false.
Queue it on many phones
One request, one entry per run. Here, three runs on three of your phones.
3.0Step 2from axilio import RunConfigfrom axilio.platform import Clientclient = Client() # reads AXILIO_API_KEY# One entry per run, each pinned to one of your dedicated phones.phones = ["ph_123", "ph_456", "ph_789"]result = client.runs.create("wf_123",runs=[RunConfig(phone_id=phone, variables=[{}]) for phone in phones],start_timeout_seconds=300, # how long a run may wait for its phone)print(result.run_ids)
Book runs for later
Add start_at to the same request and the runs start at that time instead of now. It works in the API and the dashboard today; the SDKs take it from their next release, shown here.
4.0Scheduling
from datetime import datetime, time, timedelta, timezonefrom axilio import RunConfigfrom axilio.platform import Clientclient = Client() # reads AXILIO_API_KEY# Tomorrow at 9:00 UTC, on the same three phones.tomorrow = datetime.now(timezone.utc).date() + timedelta(days=1)phones = ["ph_123", "ph_456", "ph_789"]result = client.runs.create("wf_123",runs=[RunConfig(phone_id=phone, variables=[{}]) for phone in phones],start_at=datetime.combine(tomorrow, time(9, 0), tzinfo=timezone.utc),)print(result.run_ids) # listed as scheduled until then# Plans changed? Cancel a booked run any time before it starts:# client.runs.cancel(run_id)
Waits as scheduled
Booked runs list as scheduled and don't hold a phone until their time comes. Book up to 30 days ahead.
Starts on time
Within about 15 seconds of start_at, plus the usual wait for a phone. The queue timeout counts from then.
Cancel until it starts
runs.cancel stops a booked run before it starts. Each booking runs once; book again to run it again.
Follow the runs and read the results
Every run reports its status and leaves a trace and a recording behind.
5.0Step 3axilio runs list --workflow wf_123 # status of each runaxilio runs watch run_123 # follow one run's trace to the endaxilio runs stats wf_123 # total runs and success rate
Status and errors
Each run reports its status, whether it succeeded, its error message and its session ID.
Output and steps
A run's output and errors land in its trace: the Console shows what it printed, the Timeline each step.
The screen
Every run is a phone session: watch it live in the dashboard and replay its recording afterwards.
Success rate
runs stats gives a workflow's total runs and the share that succeeded.
Questions
Short answers to what people ask first.
6.0FAQ
Up to 1,000. Each entry in runs is one run, and each gets its own phone session.
As many as your phones and concurrency allow. The rest wait in the queue until a phone is free or their queue timeout passes.
Yes. Set start_at on the request, or pick a start time in the dashboard, up to 30 days ahead. The runs list as scheduled, can be canceled until then, and start within about 15 seconds of that time plus the wait for a phone. Each booking runs once. The Python and Go SDKs take start_at from their next release; until then, book from the API or the dashboard.
Yes. Each run entry carries its own variables. They're stored as plaintext, so never pass passwords or API keys.
Into its trace. The Console shows its output and errors on the same timeline as its steps; there's no separate logs field on the run. Watch and replay a session →
$15 a day, $75 a week or $180 a month per dedicated phone, with unlimited hours. Reading text with the default model is free; describing a target uses a vision model, billed per call. Pricing →