What Agents Can Do

Flows: do a task once, replay it with no model

Tasks you repeat are kept as flows: reviewed per-app scripts that replay without a model, so they cost no tokens. An agent finds the flows for an app on its own, runs one in a single call, and after a multi-step task with no flow it asks whether you want to keep what it just did.

What a flow is

A flow is a strict JSON file (version: 1) with the same guarded steps as phone_run_steps (taps by locator, launch_app, typing, wait_for checkpoints and so on) plus named string inputs. The iphone-use-mcp binary validates and runs one without any model in the loop. A flow stops at the first failed step and never retries.

bash
$ MCP="$HOME/Applications/iPhoneUse.app/Contents/MacOS/iphone-use-mcp"
$ "$MCP" flow validate examples/flows/search-spotlight.json          # offline
$ IPHONE_USE_TOKEN=… "$MCP" flow run examples/flows/search-spotlight.json --input 'query=coffee'

How agents use flows

🔎 Found on entering an app

A launch_app response, or the first screen read in a newly entered app, carries a registry block listing the saved flows for that app. If one does the task, the agent runs it with phone_flow_run: one call instead of dozens.

💾 Offered after a task

Do you want me to save this as a flow?

When a response carries flow_suggestion, or a multi-step task finished with no flow, the agent asks you. The daemon has already recorded the steps as a draft.

Saving only happens when you agree:

  1. Draft: the agent gets the draft (phone_flow_draft, or flow draft --out my-task.json), with a todo list of things to fix.
  2. Fix and check: it fixes the todo list, validates the file and runs it once on the phone.
  3. Publish, with your OK: publishing opens a public PR to the registry, so the agent asks again before phone_flow_publish(confirm=true).

IPHONE_USE_FLOWS_NO_SUGGEST=1 silences the save suggestions.


Record one in the browser

The Flow panel on the control page records what you do on the phone into a replayable flow file:

The official registry

leeguooooo/iphone-use-flows is the official, and the only supported, source of reviewed per-app flows. The daemon keeps it fresh by itself (IPHONE_USE_FLOWS_NO_AUTO_UPDATE=1 turns that off). Files are pure JSON, so installing the registry never executes code; a checksum or validation failure aborts the whole update and leaves the store untouched.

bash
$ "$MCP" flow update                        # mirror into ~/.iphone-use/flows: sha256 + strict validation
$ "$MCP" flow list --category health        # id · risk · verified · inputs · name
$ "$MCP" flow info health/export-all-zh-cn  # metadata and step templates
$ "$MCP" flow run health/export-all-zh-cn   # failures say which step and why
$ "$MCP" flow draft --out my-task.json      # what you just did, as a draft flow
$ "$MCP" flow add my.json --as myapp/daily  # your own flow; survives update
$ "$MCP" flow publish my.json --as myapp/daily --alias MyApp --note "iPhone 17 Pro Max, iOS 26"   # opens the PR via gh
$ "$MCP" flow report health/export-all --result @run.json --note "profile button renamed"           # files a flow-broken issue

Risk levels

riskMeaning
read_onlyReads the phone only.
navigationMoves around the app.
side_effectSends, publishes, pays or deletes. Refuses to run without --confirm / confirm=true.

When the app updates

Each flow records the app (or iOS) version it was proved on, the CLI reads what the phone has installed (flow apps), and every listing shows a compat verdict: verified, untested-newer, incompatible, broken, needs-verification, draft or unknown. flow run refuses broken or incompatible flows without --force. A nightly canary re-runs the verified read-only flows on a real phone: verified refreshes the date, failed tags the flow and files a flow-broken issue, and skipped (phone locked, owned, not drivable, or outcome unknown) leaves the flow exactly as it was.

When a run fails

The result grows a diagnosis block: the failed step, whether the screen could be read at all, a reason such as locator_no_match or locator_ambiguous, and up to five candidate elements. It is one bounded read after the run: nothing is re-sent and the flow is never silently edited. --artifacts-dir DIR also writes a machine-readable record of the run (structure only: typed input and screen text are never written).

⚠️ Keep secrets out of inputs
--input KEY=VALUE resolves only for the current run and is never written back, but command-line values can appear in shell history. Flow inputs must not carry credentials, codes or private content, and send, publish, pay and delete actions must be declared side_effect.

Test suites and scheduled runs

Two things build on flows. Both run through the same engine as flow run.

🧪 Test suites

iphone-use-mcp test suite.yaml turns "open it, tap around, check it's right" into a file you can rerun. Exit code 0 every case passed, 1 a case failed, 2 the suite is invalid or the phone cannot be driven. --junit FILE writes a JUnit XML report for CI.

⏰ Schedules

The daemon runs a flow or a suite on a cron line. It waits when someone else is using the phone, and a failed, missed or skipped run raises a macOS notification. A side-effect target needs --confirm when you create the schedule.

bash
$ iphone-use-mcp test examples/tests/settings-smoke.zh-CN.yaml --junit report.xml
$ iphone-use-mcp schedule add --cron "0 9 * * 1-5" --test ~/suites/smoke.yaml --name "morning smoke"
$ iphone-use-mcp schedule add --cron "@daily" --flow health/export-all-zh-cn
$ iphone-use-mcp schedule list

The same schedule list is on the control page at /schedules. Details: Testing and scheduled runs.

Next: what to ask your agent · connect your agent.