Skip to main content
Glama

flow-execute

Turn an authored YAML flow into a single run that replays UI actions on a mobile simulator or emulator and reports each step's pass/fail verdict.

Instructions

Run a saved flow from the .argent/flows/ directory, or an explicit boundary-managed flow_path. Use when a scenario is already authored as YAML and the whole of it should replay in one call with a per-step verdict; reach for the individual gesture tools when nothing is authored yet, and for run-sequence when the steps are an ad-hoc list rather than a stored flow. Steps run in order: launch starts an app from scratch (terminate + relaunch) and waits until it is ready (on iOS it also pins later element lookups to that app rather than auto-detecting the frontmost one); tool calls dispatch through the registry (a raw tool step ends that iOS pin, so lookups auto-detect again until the next launch, though a tool that cannot change the foreground app leaves the launched id as a fallback for a timed-out auto-detect, and launch-app/restart-app leave the id they started as that fallback instead); tap/long-press/type resolve a selector to an element and act on it (tap: { on, times: 2 } double-taps; long-press: { on, duration } presses and holds; tap/long-press alternatively take a raw normalized point — bare { x, y } or on: { x, y }; any selector may scope its matches geometrically, the CSS combinators read off frames: within: <selector> (descendant — inside that container's frame), after: <selector> (CSS ~ — following it in reading order), next: <selector> (CSS + — the nearest such follower, which unlike CSS reaches past a non-matching neighbour rather than failing), plus any: true (CSS * — legal only WITH a scope and never beside text/id/role). Scopes nest to disambiguate — within: { id: card, within: { id: list } } reads "inside card inside list", each container's frame inside the next); swipe performs one finger flick (swipe: left, or swipe: { from?, direction|to|by, momentum?, duration? } — direction is the FINGER's travel, the opposite sense of scroll-to's content direction; by: { x?, y? } — signed 0–1 screen fractions, combined length at least 0.03 (a diagonal clears it where neither axis does); duration in ms, default 300, minimum 150, maximum 10000; each bound is a parse error that rejects the file before any step runs; momentum: false lands exactly where the finger lifts instead of flinging); scroll-to scrolls (momentum-free) until a target is visible; pinch zooms (pinch: { on?, scale } — scale > 1 in, < 1 out; screen center when on is omitted); rotate is the two-finger rotation gesture (rotate: { on?, by } — degrees, + clockwise, within ±3000°; screen center when on is omitted; distinct from the rotate tool, which changes device orientation); await waits for a UI condition, and additionally takes the one condition that has no selector: idle: true waits until the screen has content and stops moving in BOTH the UI tree and the rendered pixels (it never fails a run — a screen that never settles passes carrying a warning, which is what makes it safe to persist; the one idle outcome that does stop the run is an error for a tree source THIS step could not read at all — a broken window rather than a verdict about the app, which leaves the run not-ok and skips every later step; it says nothing about WHICH screen settled — a dropped tap leaves the source screen perfectly idle — so pair it with the element check that names the destination); wait pauses for a fixed number of milliseconds; assert checks one now; snapshot diffs a screenshot — or, with cropOn: <selector>, one element's cropped region — against a stored baseline (a missing baseline fails the step — set updateBaselines to adopt the current screen; a cropped element whose size drifted fails on dimensions); echo annotates; run executes another flow inline — a YAML path resolved against the directory of the flow file that references it (co-located runs only). A selector-less gesture — a coordinate tap/long-press/swipe, or a pinch/rotate with no on — resolves no frame out of the tree, so an unreadable tree source does NOT stop it the way it stops idle: it settles best-effort, dispatches anyway, and the step PASSES carrying a warning that quotes the source's own error. That green says the gesture was SENT, not that it landed. Restore the tree source (usually relaunch the app so the instrumentation loads), or accept the warning where the app can serve no tree; the first such gesture proves the outage and later ones spend that verdict without paying the settle window again. A tree read that comes back, or a relaunch, retires that verdict — which only makes the next gesture pay a fresh window, and it warns again if the source is still down. A when: block (condition + steps:, no else) runs its steps only if the condition holds — checked once with the short assert grace — for one-sided divergences like interstitials and coach marks; a skipped block reports distinctly and failures inside an entered block are real failures. A flow that begins with a launch step is a self-contained e2e flow; one that doesn't runs against the device's current state. Device id is injected by the runner (flows store none) — pass device or platform to pick one, else the single booted device is used. On Chromium a launch step's value is an Electron app path ({ chromium: | { path, args } }) the runner boots (on the tool-server host) rather than an installed app id it relaunches. With no explicit device, a run whose leading launch is unambiguously chromium (platform: chromium, or a lone { chromium: … } target) boots that app and starts there — following a leading run:, so a fragment that composes a chromium e2e flow boots too; otherwise the first launch attaches to an already-running instance and never kills it. Every later launch — a nested e2e flow's own, or a mid-flow relaunch — boots a fresh instance the run moves onto; an instance the run already owns for that same app is killed first (its exit awaited) so the replacement can't lose the race against its single-instance lock. Instances the runner still owns at run end are torn down then. A launch declaring no id for the run's platform is an error, not a cue to switch platforms. Every step hard-stops the flow on failure; later steps are reported as skipped. Returns a structured report ({ flow, device, executionPrerequisite, ok, aborted?, passed, failed, skipped, errored, steps }) — device is the device the run STARTED on; when launches moved it onto runner-booted instances, each names its instance in that step's reason and marks the move — run moved off <id>, or retired <id> (same app relaunched) when the instance it left was the one killed — a relaunch that retired an older owned instance names both.

If a fragment has an execution prerequisite and prerequisiteAcknowledged is not set to true, the tool returns a notice with the prerequisite instead of running. Pass exactly one flow source: name for a saved flow under project_root, or flow_path for an explicit YAML — both together, or neither, fails the call.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameNoName of a saved flow to run from `.argent/flows` (e.g. "settings-explore"). Omit when flow_path is set.
deviceNoDevice id to run against (iOS UDID, Android/Vega serial, Chromium id) — the id list-devices reports. Auto-detected when omitted, but only when exactly one booted device matches (optionally narrowed by `platform`); with several booted the run fails and lists them, so pass this explicitly whenever more than one device is up.
platformNoRestrict auto-detection to this platform when several devices are booted. `chromium` does more than filter: with no `device` it SELECTS the self-boot branch for an e2e flow - the runner boots an Electron instance from the `launch` step's chromium value and tears it down after the run (a single-key `launch: { chromium: … }` map selects it on its own, without this parameter). When it selects that branch it never falls back to device auto-detection (a fragment, or an e2e launch map with no `chromium` key, still does), and the launch value must be a real Electron app path on the tool-server host: a bare-string `launch:` - what the recorder writes - holds an installed-app bundle id, so passing `chromium` for one fails the whole run with `Electron boot: path does not exist`. Edit the launch to `{ chromium: <app path> }` first.
flow_fileNoPath to the flow .yaml as readable by the tool-server. Internal — the argent client derives it from project_root and name automatically; leave unset.
flow_pathNoOmit when name is set. Absolute path to a co-located flow .yaml on the client and tool server's shared filesystem. This must be supplied through the file-input boundary. For remote execution, pass name + project_root instead.
project_rootYesAbsolute path to the calling agent's project root — the cwd it is working in. With name, the saved flow is read from `.argent/flows/<name>.yaml` under this root; with flow_path, the flow, its run: siblings, and baselines all resolve beside the YAML instead, so pass the agent's cwd.
updateBaselinesNoWrite/refresh screenshot baselines for `snapshot` steps instead of diffing against them.
prerequisiteAcknowledgedNoSet to true to confirm the execution prerequisite has been met. Required (LLM path) when a fragment defines an executionPrerequisite.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed2 schema fields changedv0.22.0
    • removedInput schema / oneOf
      Removed value: -[
      -  {
      -    "required": [
      -      "name"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "flow_path"
      -    ]
      -  }
      -]
    • changedInput schema / properties / flow_path / description
      Previous value: -"Absolute path to a co-located flow .yaml on the client and tool server's shared filesystem. This must be supplied through the file-input boundary. For remote execution, pass name + project_root instead."New value: +"Omit when name is set. Absolute path to a co-located flow .yaml on the client and tool server's shared filesystem. This must be supplied through the file-input boundary. For remote execution, pass name + project_root instead."
  2. Changed2 schema fields changedv0.20.0
    • changedInput schema / properties / device / description
      Previous value: -"Device id to run against (iOS UDID, Android/Vega serial, Chromium id). Auto-detected when omitted."New value: +"Device id to run against (iOS UDID, Android/Vega serial, Chromium id) — the id list-devices reports. Auto-detected when omitted, but only when exactly one booted device matches (optionally narrowed by `platform`); with several booted the run fails and lists them, so pass this explicitly whenever more than one device is up."
    • changedInput schema / properties / platform / description
      Previous value: -"Restrict auto-detection to this platform when several devices are booted."New value: +"Restrict auto-detection to this platform when several devices are booted. `chromium` does more than filter: with no `device` it SELECTS the self-boot branch for an e2e flow - the runner boots an Electron instance from the `launch` step's chromium value and tears it down after the run (a single-key `launch: { chromium: … }` map selects it on its own, without this parameter). When it selects that branch it never falls back to device auto-detection (a fragment, or an e2e launch map with no `chromium` key, still does), and the launch value must be a real Electron app path on the tool-server host: a bare-string `launch:` - what the recorder writes - holds an installed-app bundle id, so passing `chromium` for one fails the whole run with `Electron boot: path does not exist`. Edit the launch to `{ chromium: <app path> }` first."
  3. Changed5 schema fields changedv0.19.0
    • addedInput schema / oneOf
      Added value: +[
      +  {
      +    "required": [
      +      "name"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "flow_path"
      +    ]
      +  }
      +]
    • addedInput schema / properties / flow_path
      Added value: +{
      +  "description": "Absolute path to a co-located flow .yaml on the client and tool server's shared filesystem. This must be supplied through the file-input boundary. For remote execution, pass name + project_root instead.",
      +  "type": "string"
      +}
    • changedInput schema / properties / name / description
      Previous value: -"Name of the flow to run (e.g. \"settings-explore\")"New value: +"Name of a saved flow to run from `.argent/flows` (e.g. \"settings-explore\"). Omit when flow_path is set."
    • changedInput schema / properties / project_root / description
      Previous value: -"Absolute path to the project root directory that contains `.argent/flows/<name>.yaml`."New value: +"Absolute path to the calling agent's project root — the cwd it is working in. With name, the saved flow is read from `.argent/flows/<name>.yaml` under this root; with flow_path, the flow, its run: siblings, and baselines all resolve beside the YAML instead, so pass the agent's cwd."
    • changedInput schema / required
      Previous value: -[
      -  "name",
      -  "project_root"
      -]New value: +[
      +  "project_root"
      +]
  4. Changed4 schema fields changedv0.16.0
    • addedInput schema / properties / device
      Added value: +{
      +  "description": "Device id to run against (iOS UDID, Android/Vega serial, Chromium id). Auto-detected when omitted.",
      +  "type": "string"
      +}
    • addedInput schema / properties / platform
      Added value: +{
      +  "description": "Restrict auto-detection to this platform when several devices are booted.",
      +  "enum": [
      +    "ios",
      +    "android",
      +    "chromium",
      +    "vega"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / prerequisiteAcknowledged / description
      Previous value: -"Set to true to confirm the execution prerequisite has been met. Required when the flow defines an executionPrerequisite."New value: +"Set to true to confirm the execution prerequisite has been met. Required (LLM path) when a fragment defines an executionPrerequisite."
    • addedInput schema / properties / updateBaselines
      Added value: +{
      +  "description": "Write/refresh screenshot baselines for `snapshot` steps instead of diffing against them.",
      +  "type": "boolean"
      +}
  5. First observedv0.15.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden—and it delivers. It discloses execution order (launch, tool, tap, swipe, scroll-to, etc.), side effects (iOS pinning, instance teardown, baseline updates), failure semantics (hard-stop, skipped later steps), and the exact structure of the returned report. It even explains edge cases like how selector-less gestures handle unreadable tree sources and how warnings differ from errors. This is exceptional behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but the tool is exceptionally complex—8 parameters, many step types, many edge cases. It is front-loaded with the primary use case and then systematically walks through each step kind. Some sentences are densely packed and use nested parentheticals that could be easier to parse, but every sentence adds factual content; there is no filler. For the complexity, this level of detail is justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must explain return values—and it does: "Returns a structured report ({ flow, device, executionPrerequisite, ok, aborted?, passed, failed, skipped, errored, steps })" plus details on device field semantics. It also covers prerequisites, device selection, chromium-specific behavior, and error conditions. Given the tool's complexity and the absence of an output schema, the description is fully complete for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, yet the description still adds substantial meaning beyond the schema. It clarifies that device auto-detection only works when exactly one booted device matches, that platform=chromium selects a self-boot branch with fallback rules, that project_root resolves flow files/baselines differently depending on name vs flow_path, and that updateBaselines alters snapshot behavior. These operational details are not fully captured in the schema property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states precisely what the tool does: "Run a saved flow from the .argent/flows/ directory, or an explicit boundary-managed flow_path." It names the resource (flows, YAML) and the action (run), and later distinguishes itself from siblings by saying to use individual gesture tools when nothing is authored and run-sequence for ad-hoc lists. This is a clear, specific description that an agent can act on.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool versus alternatives: "Use when a scenario is already authored as YAML and the whole of it should replay in one call... reach for the individual gesture tools when nothing is authored yet, and for run-sequence when the steps are an ad-hoc list rather than a stored flow." It also provides rules for choosing between name and flow_path, and warns about the prerequisiteAcknowledged flow. This leaves no ambiguity about invocation context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/software-mansion/argent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server