Skip to content

Chain β€” Batched Sub-Actions

Android Supported iOS Supported

chain runs an ordered list of sub-actions in a single tool call, settling between each one. It’s the agent-loop cousin of run_flow: where run_flow batches an MCP round-trip, chain lets the agent collapse a short β€œdo this, then this, then this” into one step without re-reading the screen between every action.

Each sub-action is {"tool": "<name>", "args": {...}}:

chain({"actions": [
{"tool": "launch_app", "args": {"package": "com.android.settings"}},
{"tool": "find_on_screen", "args": {"text": "Wi-Fi"}},
{"tool": "tap", "args": {"x": 540, "y": 300}}
]})

The settle param controls the pause between sub-actions:

  • "stabilize" (default) β€” a fixed 0.6 s settle so the UI can catch up.
  • "delay" β€” sleep delay_ms (default 600 ms, capped at 3 s).

No settle runs after the final action.

  • Max 15 actions per chain; a longer batch is refused.
  • The whole batch is validated before anything runs. Every sub-action’s tool must be in the safe-tool allow-list (SAFE_DEVICE_TOOLS) β€” if any step names a disallowed tool, the entire chain is refused and nothing executes. A chain can’t hide a privileged call after a few benign steps.
  • Chains can’t nest (a step naming chain is refused).
  • At runtime, the first sub-action that raises aborts the rest of the chain and reports how far it got.

chain is a meta-executor, so it’s EXEC_CAPABLE, not SAFE β€” it can’t be smuggled inside a run_flow or another chain. Its own children stay restricted to the safe allow-list, so higher-privilege tools (like sub_agent) can never run inside a chain.