Automation Skill Builder
All posts Home

Product blog

From linear recording to loops and branches

Field notes on turning a one-off MCP recording into batch automation — without recording every branch by hand. Companion article: measured time, cost, and when to switch methods.

Three ways to build the same flow

A typical goal: after login, scan a list, open rows that match a rule, and run the same sub-flow on each. Teams usually choose one of three authoring paths. We originally covered loops, branches, and this comparison in one discussion; it is now split into two posts so each can stand alone — this one is the hands-on playbook, the other is ROI and method choice.

Measured build time, GLM-5 API cost (OpenRouter vs SiliconFlow), ASB subscription, and nesting crossover → see Three authoring methods — measured time and ROI and the interactive calculator linked at the end.

From here on we assume a linear recorded script (Method 3). If you later need the same inner steps in several outer flows, reuse the inner recording as Method 2’s packaged block instead of re-refactoring one large script.

A common starting point is a linear Python script: every click and fill is hard-coded in order. That is exactly what recording produces, and it is a good artifact — not the final form.

The productive move is to paste the script to your AI partner (in the IDE or Automation Skill Builder) and describe intent in plain language: which lines repeat, what data drives the loop, and what should happen on failure.

Turn repetition into a loop

Example: three table rows were recorded as separate click/fill pairs. Tell the model:

# recorded (linear) click("btn_row_1"); fill("input_row_1", "A") click("btn_row_2"); fill("input_row_2", "B") click("btn_row_3"); fill("input_row_3", "C")

Ask for a data-driven loop (Excel/CSV or a list). Typical refactor:

data = ["A", "B", "C"] for i, val in enumerate(data, 1): click(f"btn_row_{i}") fill(f"input_row_{i}", val)

Parameterize selectors, add per-row try/except, and insert waits inside the loop — not only at the end.

If/else without recording both paths

You do not need to record success and failure separately for simple branches.

Operations come from recording; business rules come from your description. The model is not guessing policy — it is wiring checks you specify (is_visible, get_text, exists).

MCP recording while the AI operates

Recording does not have to mean manual clicking. Start recording, then let the AI drive Playwright through MCP — the same business sentence applies to Method 1 and Method 3 (“open the first row where Customer contains Acme”).

The difference is workflow shape: Method 3 captures one verified run, then refactors in a clean context. Method 1 often mixes exploration, fixes, and generation in one growing chat — which raises rounds and tokens even when the underlying tools are the same.

What actually costs time in practice

In a measured Method 3 run (~25 minutes, ~3 debug rounds), time went to:

If you know the system well, three rounds is realistic; on an unfamiliar UI, budget more time for the same three classes of fixes.

Separate “find a run” from “generalize”

Program synthesis research matches what we see: example-guided generalization (one runnable trace → loop) is far more stable than specification-only codegen (NL → final program in one shot).

Method 1 can copy the same split: phase A — run once via MCP and collect selectors; phase B — new chat, paste trace, ask for the loop. That narrows the gap with Method 3; recording still forces the two-phase habit by default.

For a list-filter scenario (pick rows matching a rule, open each, run a fixed sub-flow), start with full record + AI refactor. When the same inner flow appears in several outers or nesting depth grows, graduate to inner record → parameterized skill/exe → outer run_code — covered in the ROI article.