Start

Goals that pass

How to phrase a goal so the model does what you mean.

The model sees the accessibility tree of the current screen (every control with its label and position, and the visible text) plus your goal, the flow's data, and what it did so far. It does not see pixels unless a step is escalated. Writing for that reader is most of the skill.

Name what is on screen

The model matches your words against control labels. Use the label the app shows, in quotes if it is short.

  • Weak: Log the outfit. There is a Log tab, a "Log it" button, and a "Log a wear" button; the model picks one.
  • Strong: Tap "Choose pieces", pick one, tap Done, then tap "Log it".

If a control has no accessible name, the tree shows it as (unlabeled button) with the text nearest to it. Name that neighbour ("the button next to WHEN") or, better, give the control a label in the app. testedok audit lists every nameless control.

Say where things are when it matters

"Scroll down to find 'Log it' at the bottom" beats "tap Log it" when the button starts below the fold. Controls hidden under a tab bar or off screen are not offered to the model until they scroll into view.

Put values in data, not in the sentence

"goal": "Create a list named after list_name and tap Done",
"data": { "list_name": "Groceries {{run}}" }

The model then types the value exactly, and secrets and leased accounts drop in the same way. A value inside the goal text also works, but the model may paraphrase it.

One flow, one thing

A flow that signs up, browses, buys and signs out is four flows. Short flows replay better, fail more precisely, and are cheaper. Use requires to chain them when one depends on another's state.

Expect something the app shows

expectText is checked against what the screen shows, not what you typed. "Groceries {{run}}" in a list of lists is a good expectation; the same text still sitting in the field you typed it into is not.

Use context for what is always true

Facts about the app that every flow needs, such as which demo accounts exist, what an unlabelled control is, or that a code field accepts any six digits, belong in the project's context (Settings → What flows should know), not repeated in every goal. A flow's own context adds to it.

When it is unsure

A step with low confidence is escalated: a vision model gets a screenshot and decides that step. You see it in the log as Claude decides …. If a flow escalates every time at the same step, the screen is probably ambiguous to the tree: a custom control without a label, a selected state the app does not expose. Fix the label; the flow gets faster and cheaper.

Read the failure

A failed run says which step, why, and what was on screen. The run page shows the screenshot and tree of every step. Most first failures are wording: the model did something reasonable that was not what you meant. Reword, run again; the route from the passing run makes the next runs cheap.