--- name: runmacro-workflow summary: Generate 100% valid RunMacro browser automation workflow JSON (schema runmacro.workflow_import.v1) for direct import into the RunMacro "Import Workflow JSON" dialog. --- # RunMacro Workflow Import Specification for AI Agents This document teaches AI agents (ChatGPT, Custom GPTs, Gemini Gems, Claude) how to generate valid, robust, production-ready workflow JSON files that can be pasted directly into RunMacro's **"Import Workflow JSON"** (Nhập workflow JSON) dialog without any schema or validation errors. --- ## 1. Ten Absolute Golden Rules (Strict Enforcement) Every JSON output **MUST** strictly follow all 10 rules below. Violating any one will cause RunMacro to reject the import immediately. 1. **Exact Schema Version**: - `"schema_version"` MUST be exactly `"runmacro.workflow_import.v1"`. 2. **Exact Mode**: - `"mode"` MUST be exactly `"browser"`. 3. **Only 3 Allowed Root Keys**: - The root JSON object MUST contain **ONLY** these 3 keys: `"schema_version"`, `"mode"`, `"nodes"`. - ❌ **NEVER** add extra root keys such as `"name"`, `"description"`, `"steps"`, `"actions"`, `"version"`, `"author"`. Any unknown key triggers an immediate `[import.unknown_field]` rejection. 4. **All Commands Inside `nodes` Array**: - Every execution step must be placed inside the `"nodes"` array. 5. **Exact Command Node Structure**: ```json { "kind": "command", "public_type": "", "public_version": 1, "arguments": { ... } } ``` 6. **MANDATORY: 6,000ms Delay Immediately After Opening a URL (`SMART_RECORD_NAVIGATE_DELAY_MS`)**: - After every `browser.open_url` command, you **MUST** immediately insert a `flow.delay` node with exactly 6000ms: ```json { "kind": "command", "public_type": "flow.delay", "public_version": 1, "arguments": { "ms": 6000 } } ``` - *Technical reason*: The browser needs at least 6 seconds to establish a CDP session, load JavaScript bundles, and render the DOM. Without this delay, the next command runs against an empty DOM and fails with `not_found`. 7. **MANDATORY: 2,000ms–3,000ms Settle Delay After Enter / Search Submit**: - After pressing Enter (`keyboard.key_press` with `"key": "Enter"`) or clicking a search/submit button, you **MUST** insert a `flow.delay` of 2000ms–3000ms to allow the page to load results. 8. **MANDATORY: Multi-Candidate Fallback Selectors (2 to 4 Candidates)**: - **NEVER** guess only a single CSS selector. - Always provide **2 to 4 fallback candidates** in `selectorCandidates`, ordered by priority: - `priority 10`: Semantic attribute selector (`name`, `id`, `aria-label`). - `priority 20`: Tag + attribute or fallback ID selector. - `priority 30`: Parent–child or Web Component structure (e.g. `ytd-searchbox input`). - `priority 40`: Broad class-based or CSS path selector. 9. **MANDATORY: Verify Page Navigation by URL, Not by Element Selector**: - When verifying a page transition, use `browser.smart_assert_url_contains` with a stable URL landmark (strip dynamic query params like tokens, timestamps). - Do not rely on element existence to confirm navigation — ads and pop-ups can block elements unpredictably. 10. **Pure JSON Output Only**: - Return ONLY a valid JSON block (wrapped in a single ```json fence). Do not include greeting text, commentary, or explanations outside the JSON block. --- ## 2. Supported Command Catalog (`public_type`) All commands use `"public_version": 1`. ### A. Navigation & Tab Management | `public_type` | `arguments` | Description | | :--- | :--- | :--- | | `browser.open_url` | `{"url": "https://...", "open_mode": "current"}` | Open URL in current tab (`"current"`) or new tab (`"new"`). Always followed by a 6,000ms delay. | | `browser.reload` | `{"ignore_cache": false}` | Reload current tab. | | `browser.new_tab` | `{"url": "about:blank"}` | Open a new tab with the specified URL. | | `browser.switch_tab` | `{"tab_index": 1}` | Switch to a tab by 1-based index. | | `browser.close_tab` | `{}` | Close the active tab. | | `browser.back` | `{}` | Navigate back in browser history. | | `browser.forward` | `{}` | Navigate forward in browser history. | --- ### B. Smart DOM Interaction (`browser.smart_*`) All smart interaction commands use a `selector_profile` containing multiple fallback candidates: ```json "selector_profile": { "selectorCandidates": [ { "type": "css", "value": "input[name='q']", "strategy": "ai_css", "priority": 10 }, { "type": "css", "value": "textarea[name='q']", "strategy": "ai_css", "priority": 20 }, { "type": "css", "value": "form input[type='text']", "strategy": "ai_css", "priority": 30 } ] } ``` | `public_type` | `arguments` | Description | | :--- | :--- | :--- | | `browser.smart_type` | `{"selector_profile": {...}, "text": "value to type"}` | Type text into an input or textarea element. | | `browser.smart_click` | `{"selector_profile": {...}}` | Left-click an element. | | `browser.smart_double_click` | `{"selector_profile": {...}}` | Double-click an element. | | `browser.smart_right_click` | `{"selector_profile": {...}}` | Right-click an element. | | `browser.smart_hover` | `{"selector_profile": {...}}` | Hover over an element (triggers dropdowns/tooltips). | | `browser.smart_check` | `{"selector_profile": {...}}` | Check a checkbox or radio button. | | `browser.smart_uncheck` | `{"selector_profile": {...}}` | Uncheck a checkbox. | | `browser.smart_toggle` | `{"selector_profile": {...}}` | Toggle a checkbox state. | | `browser.smart_select_by_value` | `{"selector_profile": {...}, "text": "opt_val"}` | Select an `