Skip to content

应用开发指南

自定义应用通过可视化步骤流程编辑器构建自动化任务。每个步骤代表一个原子操作,如点击、输入、数据提取、条件判断等。步骤之间按顺序执行,支持循环和条件分支。步骤的输出可保存到变量中,后续步骤通过 {{变量名}} 引用。

变量引用规则:在参数值中使用 {{变量名}} 可引用之前步骤保存的变量。支持点号访问子字段,如 {{videoInfo.author}}。运行参数(如搜索关键词、最大视频数等)通过 {{ctx.searchKeyword}}{{ctx.maxVideos}} 等方式访问。

应用启动

启动应用(launchApp)

启动指定 Android 应用。会先强制停止应用再启动,确保从初始状态开始。

返回类型:无

参数

参数说明
uri目标应用包名

示例

  • com.ss.android.ugc.aweme(抖音)
  • com.tencent.mm(微信)
  • com.xingin.xhs(小红书)

TIP

常见应用包名可在网上搜索获取。启动后通常需要配合「随机延迟」等待应用加载完成。

终止应用(terminateApp)

强制停止指定 Android 应用。用于在启动前清理应用状态。

返回类型:无

参数

参数说明
uri要终止的应用包名

TIP

launchApp 步骤已内置终止逻辑,一般不需要单独使用此步骤。

浏览器操作

启动浏览器(browserLaunch)

启动浏览器并导航到指定 URL。用于网页类任务的第一步。

返回类型:无

参数

参数说明
url要打开的网站 URL(支持 {{变量}}
site(必填)站点标识:切换为该站点的指纹浏览器与登录态。站点在流程设计时写死,新增步骤时自动预填当前编辑会话站点。多个网站复用一套账号体系时,名称应该一样(如淘宝和天猫);对于无需账号访问的网站,也需要填写站点标识,用于生成指纹浏览器
accountName(可选)该站点的已登录账号,可填运行参数/变量(如 {{accountVar}})实现同站点多账号运行;留空 = 该站点游客模式。新增账号:点击字段右侧 + 按钮,打开指纹浏览器人工登录,完成后自动保存登录信息

示例

  • https://www.douyin.com
  • https://www.xiaohongshu.com

多站点流程示例(一个应用在单个流程内操作多个站点):

启动浏览器 url=抖音站点A页面 site=抖音 accountName=账号A   ← 抖音指纹+登录态
... 抖音操作 ...
关闭浏览器                                              ← 关闭并保存抖音登录态
启动浏览器 url=小红书页面 site=小红书 accountName=账号B   ← 切换:小红书指纹+登录态
... 小红书操作 ...
  • 切换语义:命令带 site 且与当前站点/账号不同 → 用新站点的指纹浏览器与登录态启动并导航
  • 切换时旧浏览器保留后台运行(登录态在关闭时才落盘);需要关闭旧站点浏览器时,在切换前放一步「关闭浏览器」
  • 任务结束时,流程中打开过的所有站点浏览器统一保存登录态并关闭

TIP

仅适用于网页类应用。启动后配合「随机延迟」等待页面加载。同站点同账号的登录态会自动复用(指纹一致,避免平台风控)。

切换浏览器(browserSwitch)

切回该站点的指纹浏览器——复用后台打开的最后一次活跃窗口(不导航、不重开)。用于多站点/多设备流程中「回到之前打开过的浏览器」。

返回类型:无

参数

参数说明
site(必填)站点标识:切回该站点的指纹浏览器。复用该站点后台打开的最后一次活跃窗口。多个网站复用一套账号体系时,名称应该一样(如淘宝和天猫)
accountName(可选)该站点的已登录账号;留空 = 该站点游客模式

多站点切回示例

启动浏览器 url=抖音页面 site=抖音 accountName=账号A   ← 打开抖音
启动浏览器 url=哔哩哔哩页面 site=哔哩哔哩 accountName=账号B  ← 切到B站,抖音后台保留
... B站操作 ...
切换浏览器 site=抖音 accountName=账号A                ← 切回抖音:复用后台窗口,停留在离开时的页面
... 继续抖音操作 ...
  • 与「启动浏览器」的区别:启动 = 打开 + 导航(url 必填);切换 = 回到已打开窗口(无 url,停留在上次的页面)
  • 切换回时直接复用后台浏览器窗口(不重开、不闪窗、登录态在内存中保持)
  • 目标站点浏览器已被关闭(如流程中执行了「关闭浏览器」)时,切换会打开该站点的空白浏览器(同指纹/登录态)
  • 多平台混合流程中同理:切换到手机用「启动应用」,切回浏览器用本指令

导航到 URL(browserNavigate)

在已打开的浏览器中导航到新的 URL,不重新启动浏览器。

返回类型:无

参数

参数说明
url目标 URL(支持 {{变量}}
site(可选)同「启动浏览器」:带值且与当前不同时,切换为该站点的指纹浏览器与登录态后导航;留空 = 当前浏览器
accountName(可选)同「启动浏览器」

TIP

不带 site 参数时不会创建新标签页,在当前页面内跳转;带 site 且与当前不同时执行站点切换。

关闭浏览器(browserClose)

关闭当前浏览器窗口及所有标签页,关闭前自动保存当前站点的登录态。流程中切换站点前可用本步骤显式关闭旧站点浏览器。

返回类型:无

无需参数。

WARNING

关闭后无法再执行浏览器操作,确保在所有步骤完成后再关闭。

关闭当前标签页(browserCloseTab)

仅关闭当前活跃的浏览器标签页,不影响其他标签页。

返回类型:无

无需参数。

TIP

如果只剩一个标签页则不会关闭,避免误操作。

浏览器后退(browserGoBack)

浏览器后退到上一页,相当于点击浏览器的「后退」按钮。

返回类型:无

无需参数。

TIP

仅网页端有效。不会创建新标签页,在当前页面内返回。

获取页面信息(browserInfo)

获取当前浏览器页面的 URL 和标题。返回 { url, title } 对象。

返回类型:对象

无需参数。输出保存到变量后,用 {{pageInfo.url}} 引用页面地址。

TIP

返回值需保存到变量中才能后续使用。

坐标点击(browserTap)

在网页指定坐标位置点击。适用于 AI 无法识别元素时的精确点击。

返回类型:无

参数

参数说明
x横坐标
y纵坐标

TIP

坐标值会因屏幕分辨率不同而变化,不建议跨设备使用。优先使用 AI 点击步骤。

AI 操作

AI 点击(aiTap)

AI 自动识别并点击指定元素。最常用的操作步骤,通过自然语言描述要点击的目标。

返回类型:无

参数

参数说明
prompt要点击的元素描述(AI 视觉定位,推荐)
deepLocate是否启用深度定位(可选)
selector元素选择器:CSS/XPath(web)、resource-id(Android)或 uia:/msaa:/img:(Windows 桌面,捕获控件自动生成)。优先于 prompt,可通过「捕获元素」按钮获取

示例

  • 点击右上角的搜索图标
  • 点击"发布"按钮
  • 点击评论图标

TIP

描述要具体明确:「点击视频右侧的评论图标」比「点击评论」更好。开启深度定位可提高定位精度但速度稍慢。

XPath/CSS 元素定位与捕获

AI 点击、悬停、输入等步骤以自然语言定位(prompt)为主,AI 自动理解界面元素并执行操作。当自然语言定位不准确时,可借助 XPath/CSS 元素定位(selector) 作为辅助手段。selector 和 prompt 同时填写时,优先使用 selector 精确定位,prompt 作为回退方案。

捕获元素功能:在流程编辑器中,点击 AI 操作步骤参数旁的「捕获元素」按钮(🔍图标),可以可视化的方式选取目标元素:

  1. Android 应用:自动连接设备并截取当前界面,显示所有可交互元素的高亮框

    • 鼠标移动:实时高亮命中的元素(绿色框)
    • ⌘/Ctrl + 点击:捕获元素,自动生成定位表达式(如 com.app:id/button)并回填到选择器输入框
    • 普通点击:在设备对应位置执行点击,用于在实时界面中导航(如打开菜单、进入子页面等)
    • 点击「刷新元素」:重新获取当前界面的控件树,更新元素列表
    • 右侧列表支持搜索,点击列表项选中,⌘/Ctrl + 点击列表项直接捕获
    • 属性 / XPath 模式切换(默认 XPath):属性模式生成 resource-id/text/content-desc 表达式;XPath 模式生成 //*[@resource-id='com.app:id/button'] 等 Appium 风格表达式,选中「XPath」后 ⌘/Ctrl + 点击捕获 XPath 定位符
    • Shift + 点击:设置锚点(橙色高亮),之后 ⌘/Ctrl + 点击目标元素生成「锚点 >> 目标」组合定位符,用于父子结构元素
    • 若当前界面无法获取控件树(如 Compose/WebView 应用),⌘/Ctrl + 点击会捕获屏幕坐标(格式 x,y)作为定位符
  2. 网页应用:在浏览器中进入交互拾取模式

    • 鼠标悬停实时高亮元素,按 ESC 或点击空白退出拾取模式
    • CSS / XPath 模式切换(拾取提示条右上角,默认 XPath):点击元素按当前模式生成 CSS 或 XPath 选择器并回填
    • ⌘/Ctrl + 点击:按当前模式捕获;Alt/Option + 点击:直接以 XPath 捕获(无需切换模式)
    • Shift + 点击:设置锚点(橙色高亮),之后 ⌘/Ctrl + 点击目标生成「锚点 >> 目标」组合定位符
    • 提示条可按住文字部分拖动,避免遮挡要捕获的元素
  3. Windows 桌面应用(仅 Windows 客户端):可视化捕获窗口控件,按 UIA 原生树 > 无障碍(MSAA) > 图像模板 三级链路生成 uia:{...} / msaa:{...} / img:{...} 选择器

    • 捕获弹窗展示当前屏幕截图与控件树(按窗口分组),点击控件即生成定位路径;「测试定位」可即时验证匹配
    • UIA 原生树定位不到时(如自绘控件、WebView),自动回退到无障碍树,再回退到图像模板匹配(截取控件小图 + 锚点,运行时按分辨率比例缩放匹配)
    • 图像圈选与捕获模式的悬浮提示条若遮挡目标控件,按住提示条拖走即可(框选/捕获不受影响)

校验元素:点击 AI 操作步骤参数旁的「校验元素」按钮(🧪图标),可测试选择器(含 XPath)是否能在当前页面找到匹配元素。成功时显示红框标注匹配位置,失败时提示未找到。

XPath 定位(推荐用于结构稳定的元素):

平台示例说明
Android//*[@resource-id='com.app:id/btn']按 resource-id 定位
Android//android.widget.TextView[@text='确定']按类名 + 文本定位
Androidcom.app:id/title >> .//android.widget.Button锚点 + 相对 XPath(子元素定位)
Web//*[@id='search-btn']//h3[contains(@class,'card-title')]任意 XPath 表达式
Web#header >> .search-btnCSS 锚点链(Playwright 原生支持)
桌面(Windows)uia:{...}msaa:{...}img:{...}捕获控件自动生成:UIA 原生树 > 无障碍 > 图像模板三级链

TIP

自然语言定位(prompt)为主:适用于绝大多数场景,AI 自动理解界面元素的语义并执行操作。XPath/CSS 定位(selector)为辅:当自然语言定位不准确时,可通过元素选择器精确指定目标元素。两者都填时 selector 优先,prompt 作为兜底,兼顾精确性与灵活性。

AI 悬停(aiHover)

AI 识别并将鼠标悬停在指定元素上。网页端用于触发浮层或下拉菜单。

返回类型:无

参数

参数说明
prompt要悬停的元素描述
selector元素选择器,优先于 prompt(可选)

示例

  • 悬停在用户头像上
  • 悬停在"筛选"按钮上

TIP

仅网页端有效,Android 设备无悬停操作。

AI 操作(aiAct)

AI 执行一段自然语言描述的复合操作。可描述多步操作,AI 会自动执行。是最灵活的操作步骤。

返回类型:对象

参数

参数说明
prompt操作描述

示例

  • 点击评论"你好"下方的回复按钮,输入"谢谢关注",点击发送按钮
  • 如果当前没打开评论浮层,则点击视频右侧的评论图标

TIP

可以描述条件逻辑(「如果...则...」),AI 会根据页面状态判断。操作描述要清晰、步骤明确。

AI 输入(aiInput)

AI 识别输入框并输入指定文本。先定位输入框,再输入内容。

返回类型:无

参数

参数说明
prompt输入框描述
value要输入的文本
selector输入框选择器,优先于 prompt(可选)

示例

  • prompt: 搜索输入框, value: 获客技巧
  • prompt: 评论输入框, value: {{replyContent}}

TIP

value 中使用 {{变量名}} 可以引用之前步骤的输出。

AI 滚动(aiScroll)

AI 在页面上执行滚动操作。可指定方向和距离。

返回类型:无

参数

参数说明
direction滚动方向(上/下/左/右)
scrollType滚动类型(可选)
distance滚动距离(可选)
locate滚动区域描述(可选)

示例

  • direction: , scrollType: 单次, distance: 500
  • direction: , locate: 评论区

TIP

不填 distance 时 AI 会自动判断滚动距离。填写 locate 可指定在特定区域滚动。

AI 清空输入(aiClearInput)

AI 识别输入框并清空其内容。

返回类型:无

参数

参数说明
prompt输入框描述

AI 数据提取

AI 查询(aiQuery)

AI 从屏幕中提取结构化数据,返回 JSON 对象。是最核心的数据提取步骤。

返回类型:对象

参数

参数说明
demand数据提取需求描述,包含 JSON 格式示例

示例

  • 获取视频基本信息,返回JSON格式:{ "author": "作者昵称", "description": "视频描述", "commentCount": "评论数" }
  • 获取所有评论,包括用户名和评论内容,返回JSON数组:[{"username":"用户名","content":"评论内容"}]

TIP

在 demand 中明确给出 JSON 格式示例,AI 返回结果更准确。输出保存到变量后,用 {{变量名.字段名}} 访问子字段,如 {{videoInfo.author}}

AI 提取字符串(aiString)

AI 从屏幕中提取一段文本字符串。返回纯文本而非 JSON。

返回类型:字符串

参数

参数说明
prompt要提取的文本描述

示例

  • 获取用户主页的抖音号
  • 判断当前页面状态,返回"视频详情"或"其他"

TIP

只返回一个字符串值。如需提取多个字段,请使用「AI 查询」步骤。

AI 布尔判断(aiBoolean)

AI 判断一个条件是否成立。返回 true 或 false,常用于条件判断步骤。

返回类型:布尔值

参数

参数说明
prompt判断条件描述

示例

  • 当前是否在视频播放页面
  • 评论浮层是否已打开

TIP

描述要清晰无歧义。输出保存到变量后,可在「条件判断」步骤中使用。

AI 选择下拉选项(aiSelect)

设置下拉框/组合框的选中项,输出实际选中的选项文本。优先按选择器走确定性路径(零 token):web 原生 <select> 程序化设值、自定义组件库下拉自动「展开→点选项」、Windows 桌面走 UIA 控件树选中;失败回退 AI 视觉操作(打开下拉+点击选项,消耗 token)。

返回类型:字符串(实际选中的选项文本)

参数

参数说明
selector元素选择器(CSS/XPath web、uia: windows 桌面捕获生成)。仅 web 与 Windows 桌面支持;android/macOS 平台用 prompt 描述
prompt下拉框描述(selector 为空时必填;未命中时作为 AI 兜底)
value要选中的选项(默认按显示文本包含匹配,支持 {{变量}}
by匹配方式:显示文本 / 选项值(原生 select 的 option value)/ 序号(从 0 开始)
exact精确匹配开关(默认包含匹配,多处匹配取第一个)

示例:value 填 上海(按显示文本匹配);按序号选第 2 项:by=序号、value=1

AI 获取下拉选项(aiSelectOptions)

获取下拉框/组合框的全部选项列表(含当前选中项)。web 原生 select 直接读取;自定义组件库下拉自动展开读取后关闭;Windows 桌面走 UIA 控件树枚举;其余平台 AI 视觉读取。

返回类型:数组 [{ label, value, selected }]——绑定变量后用 {{变量名.0.label}}{{变量名.1.value}} 取值,或循环遍历。

参数:与 AI 选择下拉选项相同(selector/prompt,无需 value)。

列表操作

列表类页面的专用指令:提取整屏列表数据、按行内文本点击列表项。配合「循环」「AI 操作」「代码块」实现逐屏批量处理。

点击列表项(tapListItem)

点击列表中指定某一行内的元素。选择器匹配所有行(捕获时自动生成 class 多匹配选择器),行内文本指定目标行——与滚动位置无关,列表上下滑动后依然准确。

返回类型:无

参数

参数说明
selector行内要点击的元素选择器。点击「捕获元素」自动生成匹配所有行的多匹配选择器(如 //h3[contains(@class,'card-title')]
itemText行内文本:点击所在行包含该文本的元素。可填该行任意元素的文本(标题/作者名等,部分文本也可,包含匹配)。支持 {{变量}} 引用
promptAI 兜底描述(可选):行内文本未命中时交给 AI 视觉定位的自然语言描述

示例

  • 列表场景:selector 捕获每张卡片的「关注」按钮(class 多匹配),itemText 填标题 {{comment.title}} —— 循环中对每一项点击
  • 行内文本填部分文本即可:「怎么危险的路」能命中完整标题「怎么危险的路应该先付定金…」

TIP

itemText 建议填行内唯一文本(标题、作者名等),多处匹配时取第一个。与「提取列表数据」配合:提取出列表 JSON 后,循环里用 {{item.title}} 作为 itemText 逐项点击,天然适配上下滑动。

提取列表数据(getListData)

按 XPath/CSS 提取当前屏幕可见的列表数据。每个字段一个选择器(匹配所有行),自动按行对齐成 JSON 数组 [{字段:值}, ...]

返回类型:数组(JSON 对象数组)

参数

参数说明
fields字段列表,每项含 name(字段名)和 selector(匹配所有行的 XPath/CSS)。点击字段行的「捕获元素」自动生成多匹配选择器,字段名留空自动推导
limit最多提取行数(默认 50,上限 200)

示例

json
[
  { "title": "怎么危险的路应该先付定金", "author": "晴空万里", "time": "06-19 江西" },
  { "title": "小孩子不会说话", "author": "🍁云儿🍁", "time": "06-18 广东" }
]

TIP

  • 只提取屏幕内可见的行(横竖方向都在屏幕内)——配合「循环 + 点击列表项/AI 点击 + AI 滚动」逐屏处理:提取 → 逐项处理 → 滚动 → 再提取
  • 某行缺少任一字段时整行丢弃(不错位、不补空)
  • 输出绑定到变量后,循环中通过 {{list}} 遍历,每项用 {{item.title}} 等引用字段
  • 与 AI 指令混用的典型闭环:提取列表 → 循环内用 AI 指令处理每一项 → 滚动一屏 → 再提取,直到列表结束

设备控制

获取屏幕尺寸(screenSize)

获取当前屏幕/页面尺寸(全平台:Android 设备屏幕 / Web 页面视口 / Desktop 当前显示器)。返回 { width, height } 对象。

返回类型:对象

无需参数。输出绑定到变量后(如 screen),用 {{screen.width}}{{screen.height}} 访问,或在代码块中用 screen.width 读取。

单位与 AI 滚动的距离参数一致,可直接按比例计算滚动距离。

TIP

典型用法:输出绑定到变量 → 代码块计算 scrollDist = screen.height * 0.8 → AI 滚动的滚动距离填 {{scrollDist}}(滚动一屏的 80%)。

设备滑动(deviceSwipe)

在 Android 设备上从一点滑到另一点,最精确的滑动控制。

返回类型:无

参数

参数说明
startX起点 X 坐标
startY起点 Y 坐标
endX终点 X 坐标
endY终点 Y 坐标
duration滑动时长(毫秒,可选)

示例

  • startX: 540, startY: 1500, endX: 540, endY: 500, duration: 300

TIP

推荐在需要精确控制滑动时配合「代码块」计算坐标后使用。duration 控制滑动速度,300ms 接近真人操作。

桌面自动化

桌面自动化步骤仅适用于桌面平台(platform=desktop),用于操控电脑桌面上的鼠标、键盘和显示器。

点击(computerMouseClick)

点击(单击/双击/右键/长按,跨平台)。优先按元素定位点击(桌面捕获控件生成 uia:/msaa:/img: 选择器、web 填 CSS、android 填 resource-id,零 Token),元素选择器为空时按坐标 x/y 点击。

返回类型:无

参数

参数说明
clickType点击类型:click(单击)/ doubleClick(双击)/ rightClick(右键)/ longPress(长按)。单击=全平台,双击/右键=桌面与 web,长按=android
selector元素选择器(桌面=uia:/msaa:/img:,web=CSS,android=resource-id),优先于坐标
programmatic程序化触发(仅 uia: 选择器+单击):优先 UIA 程序化调用(Invoke/Toggle/Select 链)——零输入注入、不移动光标,可规避应用的远控检测;控件不支持 Pattern 时自动回退真实点击。适合标准控件应用(记事本/WinForms 等);自绘 UI(企业微信等)通常不支持会自动回退
x / y元素选择器为空时按裸坐标点击(android 为逻辑坐标)
promptAI 兜底描述(仅单击支持;selector 未命中时交给 AI 视觉定位)

键盘快捷键(computerKeyboardShortcut)

发送键盘快捷键组合,模拟键盘操作。

返回类型:无

参数

参数说明
keyName快捷键组合(如 Command+CControl+VAlt+F4

示例

  • Command+C(Mac 复制)
  • Control+V(Windows 粘贴)
  • Alt+Tab(切换窗口)

输入文本(computerType)

在桌面上输入文本,通过剪贴板粘贴实现,支持中文。

返回类型:无

参数

参数说明
text要输入的文本内容

拖拽(computerDrag)

在桌面上从一点拖拽到另一点,模拟鼠标拖拽操作。

返回类型:无

参数

参数说明
fromX起点 X 坐标
fromY起点 Y 坐标
toX终点 X 坐标
toY终点 Y 坐标
duration拖拽时长(毫秒,默认 500)

列出显示器(computerListDisplays)

列出所有可用的显示器信息。返回显示器数组。

返回类型:数组

无需参数。输出保存到变量后,每项包含显示器 ID 等信息。

元素存在/等待(computerElementExist)

判断指定元素是否存在(输出布尔值,常用于条件分支),跨平台:优先按元素选择器确定性判断(web=CSS、android=resource-id、desktop=uia:/msaa:/img: 捕获生成,零 Token),可设置轮询等待出现;元素选择器为空时按 AI 兜底描述视觉判断一次。

返回类型:布尔

参数

参数说明
selector元素选择器(多平台格式),优先于 prompt
promptAI 兜底描述(selector 为空时必填;AI 视觉判断一次,不轮询)
timeoutSec轮询等待秒数:0=只判断一次;>0=轮询等待元素出现(间隔 1s),超时输出 false;AI 模式忽略

打开软件(computerLaunchApp)

启动桌面应用程序(Windows/macOS 桌面客户端):Windows 按可执行文件路径或命令名启动;macOS 支持 .app 路径或应用名(经 open 启动)。可传启动参数与等待时间。

返回类型:无

参数

参数说明
appPath应用路径:Windows 填可执行文件完整路径或命令名(如 D:\WXWork\WXWork.exenotepad);macOS 填 .app 完整路径或应用名(如 /Applications/TextEdit.appTextEdit)。支持 {{变量}},参数旁「选择文件/目录」按钮可直接弹窗选取
args启动参数(可选):传给应用的命令行参数;macOS 经 open --args 透传
waitSeconds启动后等待秒数(0-60,默认 0 不等待)

不同电脑路径不同怎么办

每台电脑安装路径不一致时,不要写死路径:在「变量与参数」面板定义输入变量(如 appPath,类型选 file),本步骤路径填 {{appPath}}。运行任务时,参数表单会显示该输入项,右侧「选择文件/目录」按钮可弹窗选取本机实际路径(Windows 选 exe,macOS 选 .app 目录),一次填写、多台电脑各填各的。

时间控制

随机延迟(randomSleep)

在最小值和最大值之间均匀随机延迟一段时间。

返回类型:无

参数

参数说明
minMs最小延迟(毫秒)
maxMs最大延迟(毫秒)

示例

  • minMs: 3000, maxMs: 8000(延迟 3-8 秒,均匀随机)
  • minMs: 500, maxMs: 1500(延迟 0.5-1.5 秒)

TIP

建议在启动应用、打开评论等耗时操作后添加延迟等待。Android 端通常 3-8 秒,网页端 2-5 秒。硬编码应用(如抖音评论回复)内部的拟人延迟不受此步骤影响。

服务端交互

写入任务输出(writeOutput)

将一条数据写入任务输出表,可在任务详情的「总体输出」中查看。支持变量引用。

返回类型:无

参数

参数说明
data输出数据(JSON,支持 {{变量名}}

示例

json
{ "source": "wechat_video", "username": "{ {comment.username} }", "content": "{ {comment.content} }", "replyContent": "{ {replyContent} }" }

TIP

这是记录任务成果的关键步骤。每次调用写入一条记录。

增加统计(incrementStat)

累加任务统计数据。统计值会在运行时实时显示在界面上。

返回类型:无

参数

参数说明
field统计字段名
value增量(默认 1)

示例

  • field: totalCommentsFetched, value: 1
  • field: totalFollowed

TIP

每 5 次操作自动刷新到数据库。常用统计字段:totalVideosBrowsed、totalCommentsFetched、totalFollowed、totalReplied、totalIntentionCustomers。

刷新统计(flushStats)

立即将缓存的统计数据写入数据库。

返回类型:无

无需参数。

TIP

统计数据会自动每 5 次操作刷新一次,一般不需要手动调用。

Redis 读取(redisGet)

从 Redis 读取指定键的值。键名会自动加上应用和用户维度的前缀,实现数据隔离。

返回类型:对象

参数

参数说明
key业务键名

示例

  • key: lastProcessedId
  • key: searchCursor

TIP

同一应用同一用户的 key 互相隔离,不同用户/应用之间不会冲突。输出保存到变量中后续使用。

Redis 写入(redisSet)

向 Redis 写入键值对,支持设置过期时间。用于持久化存储任务状态。

返回类型:无

参数

参数说明
key业务键名
value值(支持变量引用)
ttlSeconds过期时间(秒,默认 7 天)

示例

  • key: processedUsers, value: { "user123": true }, ttlSeconds: 86400(1 天后过期)

TIP

默认 7 天过期,适合日常去重。设为 0 表示永不过期。

Redis 计数(redisIncr)

递增 Redis 计数器并返回递增后的值。适合统计每日操作次数、限流控制。

返回类型:数字

参数

参数说明
key业务键名
value增量(默认 1)
ttlSeconds过期时间(秒)

示例

  • key: dailyFollows, value: 1, ttlSeconds: 86400
  • 输出 → 变量 todayFollows
  • 条件判断: todayFollows < 50

TIP

配合条件判断步骤可实现「每日最多关注50人」等限流逻辑。

Redis 键是否存在(redisKeyExists)

检查 Redis 中是否存在指定键。返回 true 或 false,常用于去重判断。

返回类型:布尔值

参数

参数说明
key业务键名(支持变量引用)

示例

  • key: user_{{comment.username}}
  • 输出 → 变量 alreadyProcessed
  • 条件判断: alreadyProcessed === false

TIP

配合 redisSet 实现完整去重:先检查是否存在 → 不存在则处理并写入标记。

追加到 Excel(excelAppend)

将数据追加写入 Excel 文件指定 Sheet 中。文件不存在则自动创建,Sheet 不存在则自动新建。

返回类型:无

参数

参数说明
filePathExcel 文件路径(如 /data/output.xlsx,支持 {{变量名}} 引用)
sheetName目标 Sheet 名称,默认 Sheet1
data要追加的数据。单条对象写入一行,对象数组写入多行。支持 {{变量名}} 引用
headers列名数组(如 ["姓名","年龄","时间"])。新建 Sheet 时写入第一行

示例

  • filePath: /data/leads.xlsx, sheetName: 抖音意向客户, data: {{outData}}, headers: ["用户名","评论内容","意向等级","时间"]

TIP

在服务器端执行,写入的是服务器上的文件路径。建议在关键数据写入后追加此步骤,用于导出分析。

多平台混合流程

创建应用时平台留空即为多平台应用(platform=multi),指令面板显示全部步骤类型,一个流程可同时操作浏览器、Android 手机与桌面。

当前设备切换

AI 操作步骤(aiTap / aiInput / aiScroll 等)作用于当前设备,由启动步骤切换:

步骤执行后当前设备
启动浏览器(browserLaunch)浏览器
切换浏览器(browserSwitch)浏览器(复用该站点后台窗口,不导航)
启动应用(launchApp)Android 手机
打开软件(computerLaunchApp)/ 电脑操作(computerMouseClick 等)PC 桌面

WARNING

每个 AI 操作步骤之前必须有对应平台的启动步骤明确操作对象,否则运行时报错「流程未明确当前操作设备」。同一平台的连续操作之间不要重复插入启动步骤。

示例(浏览器 → 手机 → 桌面):

  1. 启动浏览器(browserLaunch,url=抖音) → AI 点击「搜索」 → AI 输入关键词
  2. 启动应用(launchApp,uri=手机包名) → AI 点击「我的」 → 设备滑动
  3. 打开软件(computerLaunchApp,路径=记事本) → 点击(computerMouseClick,uia: 选择器) → 键盘快捷键

步骤级操作平台声明

AI 操作步骤(aiTap / aiAct / aiInput / aiQuery / aiString / aiBoolean / aiScroll / aiClearInput / aiHover 等)及列表步骤(tapListItem / getListData / computerMouseClick / computerElementExist)新增操作平台参数:

选项行为
自动(默认)按前置启动步骤/最近会话推断(即上表的「当前设备」机制)
浏览器 / 手机 / 桌面显式指定该步骤操作的设备,客户端按平台分流到对应会话,无需前置启动步骤切换

适合「同一屏先后操作两个平台」的场景,例如:浏览器提取数据 → 桌面软件处理,两个平台会话常驻,用 platform 参数逐步骤指定操作对象。

任务目标引用(__target)

运行表单/定时任务所选的目标注入为特殊标记参数 __targetkind: "task_target"),流程中可直接引用:

表达式含义
{{__target.accounts[0].site}}默认站点标识
{{__target.accounts[0].accountName}}默认站点账号
{{__target.accounts[1].site}}第二个站点(多站点流程配合「启动浏览器」步骤的 accountName 参数)
{{__target.deviceUdid}}所选 Android 设备

大模型调用

LLM 对话(llmChat)

调用文本大模型,自定义提示词,获取 AI 生成的文本结果。用于意向判断、内容生成等场景。在服务端执行(用平台配置的文本模型,不占客户端设备)。

返回类型:字符串

参数

参数说明
systemPrompt系统提示词(定义 AI 角色)
userPrompt用户消息(待分析内容)
messages高级:直接传入 [{ role, content }] 消息数组(多轮对话)

示例

  • systemPrompt: 你是一个销售意向判断助手。分析用户评论判断意向等级。
  • userPrompt: 分析以下评论:{{comments}}
  • 输出 → 变量 llmResult
  • 代码块解析: JSON.parse(vars.get("llmResult"))

TIP

在提示词中明确要求 AI 返回 JSON 格式,方便后续用代码块解析。使用 {{变量名}} 可将之前步骤的数据传入提示词。此步骤消耗 Token 余额。

MCP 调用(mcpCall)

通过 Streamable HTTP 连接远程 MCP 服务器并调用工具——查询外部数据(数据库/接口/知识库)或执行远端操作,返回结果绑定到变量。

返回类型:对象

参数

参数说明
urlMCP 服务端点(Streamable HTTP 地址,如 https://mcp.example.com/mcp
toolName要调用的工具名
apiKeyBearer Token 认证(该服务需要时填)
arguments工具参数(JSON 字符串,如 {"owner":"xxx","repo":"yyy"},支持 {{变量}}

示例:url 填 MCP 端点,toolName 填 search_docs,arguments 填 {"query": "{{searchKeyword}}"},输出绑定变量后用 {{result.0.title}} 取字段。

WARNING

MCP 调用暂不支持单步测试运行,请通过运行整个流程验证。

脚本执行

代码块(codeBlock)

在客户端本地执行 JavaScript(默认)或 Python 代码。可读写变量、解析 JSON、进行数值计算等。是最灵活的数据处理步骤。

返回类型:对象(JS:return 的值或末行表达式;Python:result 变量)

参数

参数说明
language语言:javascript(默认)/ python
code代码。JS 整体包在 async 函数中执行,支持顶层 await;Python 详见下方「Python 代码块」

如何读取变量

使用 vars.get(变量名) 读取流程变量。可读取的内容包括:

  • 「变量与参数」面板中声明的变量(含默认值)
  • 之前步骤通过「输出」绑定保存的变量
  • 之前代码块通过 vars.set 写入的变量
javascript
// 读取单个变量
const countStr = vars.get("commentCount");

// 读取对象字段(点号或下标访问)
const width = vars.get("screen").width;
const title = vars.get("videoInfo")["title"];

两个注意点

  1. vars.get() 返回的可能是字符串(取决于变量来源),数值运算前用 Number() 转换:
    javascript
    const current = Number(vars.get("totalComments")) || 0;
  2. 运行参数 ctx 不传入沙箱,代码块内 vars.get("ctx") 拿不到。引用运行参数请用 {{ctx.xxx}} 文本替换方式(见下文「变量替换 vs vars.get」)。

如何设置变量

使用 vars.set(变量名, 值) 写入变量。代码块执行结束后,set 过的变量会自动写回流程,后续步骤即可通过 {{变量名}} 引用。

javascript
// 写入新变量(无需预先声明,自动创建)
vars.set("scrollDist", Math.round(width * 0.8));

// 覆盖已有变量(常用于跨循环累计)
const current = Number(vars.get("total")) || 0;
vars.set("total", current + newCount);

支持的类型:字符串、数字、布尔、对象、数组,以及 Set / Map(会被特殊序列化,下次 vars.get 时还原)。

Python 代码块

language 选择 python 后,代码在客户端内置 Python 运行时执行(无需本机安装 Python;旧客户端回退服务端沙箱,要求服务器 python3 3.9+)。

python
import json, math, random, hashlib, base64, collections

# 变量读写与 JS 一致
name = vars.get("name")
n = vars.get("count") or 0
vars.set("count", n + 1)
vars.set("hello", "hi " + name)

# 给全局变量 result 赋值 = 步骤输出(可绑定到变量)
result = {"sha": hashlib.md5(name.encode()).hexdigest(), "pi": round(math.pi, 3)}

与 JS 版本的区别:

说明
步骤输出给全局变量 result 赋值(不赋值则为 null)
自定义函数支持:language=python 的自定义函数以 def 名(参数): 前缀注入,仅 Python 代码块可调用(JS 函数仅 JS 代码块可调用,互不可见)
可用库仅标准库白名单:json / math / re / random / time / datetime / hashlib / base64 / string / collections / itertools / functools / copy / decimal / urllib.parse / statistics / fractions / secrets / textwrap / heapq / operator / unicodedata / difflib / bisect / types / zlib(含子模块)。os/sys/socket/io/pathlib不可导入
执行限制10 秒超时、内存 512MB、无网络访问、无文件读写(open 被禁用)
变量类型仅 JSON 类型(字符串/数字/布尔/对象/数组/null),数值范围 2^53 内

编辑器内置模块提示

自定义函数编辑器中,代码输入框下方有「JavaScript/Python 沙箱:可用模块与限制」折叠面板,按语言列出可用全局与模块白名单——数据由服务端接口实时下发,与实现保持同步。object/array 类型的输入变量会自动 parse 为对象/数组,无需手动 JSON.parse / json.loads

安全说明:Python 沙箱采用「import 白名单 + 受限内置函数 + 资源限制 + 超时强杀 + 降权运行」多层防护,可挡住脚本化攻击与绝大多数恶意代码;但由于 Python 语言特性,极端深度的沙箱逃逸无法 100% 杜绝(流程作者为受信用户,平台为私有部署)。如需强隔离请联系管理员评估容器化方案。

变量和函数需要在面板中预先定义吗?

变量:不需要预先定义。 vars.set 任意名字的变量都会自动创建并写回流程,后续步骤可直接引用。但建议在「变量与参数」面板中声明,原因是:

  1. 运行参数(isInput 勾选):任务启动时由用户填写,通过 {{ctx.变量名}} 传入流程
  2. 默认值:变量在首次赋值前就有初始值
  3. 可读性:面板中能看到流程用到的所有变量

未声明的变量只影响「看不到」,不影响使用。

函数:需要在「变量」面板的「自定义函数」Tab 中定义。 自定义函数会预先载入沙箱,代码块中才能按函数名直接调用。代码块内部自己声明的 function 只在该代码块内有效,跨代码块复用必须走「自定义函数」面板

变量替换 {{var}} vs vars.get()

两者的机制不同:

方式时机行为
{{变量名}}代码执行对 code 文本做替换:整个参数就是一个 {{var}} 时保持原始类型;嵌入在字符串中时,对象会被序列化为 JSON 字符串
vars.get/set代码执行运行时读写真实变量值,类型完整保留

推荐:代码块内统一用 vars.get/set 读写变量,避免文本替换带来的引号转义问题; 替换仅用于引用运行参数({{ctx.searchKeyword}})或个别标量值。

javascript
// 不推荐:把对象用模板替换嵌入代码(依赖 JSON 序列化结果)
// const list = 模板变量替换;

// 推荐:运行时读取,类型安全
const list = vars.get("listData");

运行环境与依赖管理

代码块在客户端本地执行(新版客户端上报 codeblock-js/py 能力后自动走本地;旧客户端回退服务端沙箱):

JavaScript(本地 Node 环境)

  • 可直接 require Node 内置模块(fspathcryptohttps 等,具备完整本地能力:读写文件、发网络请求)
  • 第三方 npm 包:点击代码块编辑器下方的「依赖管理」安装(如 dayjsxlsx),安装后在代码中直接 require
  • 可用全局:vars.get/setplatform(客户端系统)、md5(文本)console.log(运行日志可见)
  • 默认超时 60 秒(可在「超时」处调整 5-600 秒)

Python(本地运行时)

  • 客户端内置 Python 运行时(无需本机安装),仅标准库白名单:jsonmathrerandomtimedatetimehashlibbase64collections
  • 无网络与文件系统访问(如需要,用 JavaScript 代码块或「本地文件操作」指令族)
  • 可用全局:vars.get/setplatformmd5(文本);给 result 变量赋值作为输出

TIP

自定义函数(JS/Python)在代码块中按函数名直接调用,与代码块同环境执行。

示例

javascript
// 解析 LLM 返回的 JSON
const raw = vars.get("llmResult");
const parsed = JSON.parse(raw.match(/\{[\s\S]*\}/)[0]);
vars.set("intentionLevel", parsed.intentionLevel);
return parsed;
javascript
// 数值计算(配合「循环」做跨屏累计)
const current = Number(vars.get("totalComments")) || 0;
const newCount = Number(vars.get("currentScreenCount")) || 0;
vars.set("totalComments", current + newCount);
return current + newCount;

自定义函数

在应用编辑器的「变量」面板中切换到「自定义函数」Tab,可定义可复用的函数(支持 JavaScript 与 Python 两种语言)。定义后会预载入对应语言的沙箱,在「代码块」中按函数名直接调用。不使用自定义函数的代码块无需定义任何函数。

函数定义

每个函数包含以下字段:

字段说明
name函数名,在 codeBlock 中直接作为标识符调用
language实现语言:javascript(默认)/ pythonJS 函数仅 JS 代码块可调用,Python 函数仅 Python 代码块可调用,互不可见
params参数名列表(可选,逗号分隔)。动态类型:不声明参数类型,类型由调用方实参决定,对象/数组直接传参
description函数描述(可选)
code函数体。JS:async 函数体(自动包装 var 名 = async (参数) => {...});Python:只写 def 函数体(自动包装 def 名(参数): 并整体缩进 4 空格),返回值用 return

使用示例

JS 函数 parseCommentCount

name: parseCommentCount
language: javascript(默认)
params: text
code:
if (!text) return 0;
text = String(text).trim();
if (text.includes('万')) { ... }

在 JS 代码块中调用(自定义函数是 async 函数,调用时建议 await):

javascript
const count = await parseCommentCount(vars.get("commentCountStr"));
vars.set('commentCount', count);

Python 函数 formatTitle

python
name: formatTitle
language: python
params: title
code:
if not title:
    return ""
return title.strip().replace(" ", "")

在 Python 代码块中调用

python
title = formatTitle(vars.get("rawTitle"))
vars.set("title", title)
result = title

函数与代码块的执行环境

  • 函数体和代码块共享同一个沙箱:JS 函数内同样可用 vars.get/setmd5cryptoJSON 等全局对象;Python 函数内可用 vars.get/set、白名单标准库
  • 同语言函数之间可以相互调用(JS:await otherFn(...);Python:other_fn(...)
  • 代码块内直接声明的普通 function/def 仅该代码块内可用,无法跨代码块复用
  • 函数定义保存在应用的 flow_definition 中,随流程一起导入导出

流程控制

循环(loop)

循环执行子步骤。支持三种模式:计数循环、遍历数组(for-each)和条件循环(while)。

返回类型:无

参数

参数说明
loopSource数组变量名(遍历数组模式)
loopVariable循环变量名(默认 item)
breakCondition退出条件表达式
maxIterations最大迭代次数(默认 1000,防无限循环)
maxConsecutiveFailures子步骤最大连续失败次数(超过后退出循环,可选)

三种循环模式

模式配置方式breakCondition 语义典型用法
计数循环仅填 maxIterations + loopVariable无(用 maxIterations 限制)遍历 N 个视频
遍历数组loopSource「退出条件」,为 true 时提前退出遍历评论列表
条件循环breakCondition「继续条件」,为 true 时继续循环滚动加载更多

示例

  • 计数循环:maxIterations: {{maxVideos}}, loopVariable: videoIndex
  • 遍历数组:loopSource: comments, loopVariable: comment,循环体中用 {{comment.username}}{{comment.content}}
  • 条件循环:breakCondition: noNewCount < 1 && totalProcessed < 20, maxIterations: 100

循环体中的变量

变量说明
{{loopVariable}}当前项。如 {{comment.username}}
{{loopVariable.__index}}当前索引(从 0 开始)
{{loopVariable.__length}}数组长度(仅遍历数组模式)
{{loopSource}}{{loopVariable}},可互换使用

TIP

  • 计数循环中 loopVariable 的值从 1 开始(如遍历第 1 个视频时 videoIndex === 1
  • 遍历数组模式中「退出条件」为 true 时立即退出,与条件循环的「继续条件」语义相反
  • maxConsecutiveFailures 用于子步骤连续报错时自动退出,避免死循环
  • maxIterations 为数字或 {{变量名}},支持引用运行参数

条件判断(conditional)

根据条件表达式执行不同的步骤分支。支持 IF/THEN/ELSE 结构。

返回类型:无

参数

参数说明
condition条件表达式(直接引用变量名,无需

条件表达式语法

类型示例
字符串比较intentionLevel === "高"
数值比较totalFollowed >= 50
布尔判断alreadyProcessed === falseisProfile === true
逻辑组合count < 10 && hasMore === truefailed === true || isProfile === false
取反!alreadySeen

分支结构

  • then 分支:条件为 true 时执行的步骤
  • else 分支:条件为 false 时执行的步骤(可选,在编辑器中点击「+ else」添加)

示例

  • condition: intentionLevel === "高" → then: [关注用户、发送回复]
  • condition: totalFollowed >= 50 || totalReplied >= 30 → then: [停止循环]
  • condition: alreadyProcessed === false → then: [关注并回复] else: [跳过]

TIP

条件表达式中变量直接引用名称,不需要 包裹(如 commentCount > 0,不是 {{commentCount}} > 0)。

输出日志(log)

输出一条日志信息到任务日志中,用于调试和记录关键节点。

返回类型:无

参数

参数说明
message日志消息(支持变量引用)

示例

  • 开始处理第 {{i}} 个视频
  • 找到意向客户: {{comment.username}}

TIP

停止信号无需手动检查——系统在每个步骤执行前自动检查,用户点「停止」时立即生效。

设置变量(setVariable)

设置流程变量的值。用于初始化变量或更新变量值。

返回类型:无

参数

参数说明
name变量名
value变量值(支持 {{变量名}} 引用)

示例

  • name: totalProcessed, value: 0
  • name: searchKeyword, value: {{ctx.searchKeyword}}

子流程(subFlows + callSubflow)

把一段可复用的步骤抽象为子流程,主流程通过「调用子流程」步骤引用——实现复用、抽象,并提升流程可读性。子流程在本应用内定义与复用(编辑器底部面板「子流程」tab 管理)。

创建子流程

  1. 底部面板 → 「子流程」tab → 新建子流程(命名、可加用途描述)
  2. 头部下拉(或子流程列表的「编辑」)切换到该子流程——画布、变量面板、复制粘贴均作用于它(顶部有青色横幅提示当前作用域),变更随整体保存
  3. 在「变量与参数」中声明变量:勾选**「运行参数」= 输入**(调用时传值)、勾选**「输出」= 输出**(调用结束回传)
  4. 像编排主流程一样编排子流程步骤(支持循环/条件/try 等所有指令)

在主流程中调用:指令面板「流程控制」分组拖入**「调用子流程」**,选择目标子流程并填入参(支持 {{变量}});在「输出绑定」中接收返回——整体绑定得到 {输出变量名: 值} 对象,或「取值路径」填某个输出名取单个。

变量与函数可见性(完全隔离)

子流程与主流程完全隔离——子流程读不到主流程变量(要传值必须声明为输入并在调用时传入参)、内部写入不影响主流程、自带独立的自定义函数(编辑子流程时在「自定义函数」面板维护,仅子流程内可见)。跨边界传值只有两条通道:输入(入参)与输出(输出绑定)

WARNING

2026-09-05 起子流程为完全隔离语义(此前支持「读穿透」直接读主流程同名变量,已移除)。存量子流程若依赖读穿透,请把用到的主流程变量声明为子流程的输入变量并填入参。

WARNING

  • 子流程不允许递归(直接或间接调用自己,保存时校验报错);嵌套深度上限 8 层
  • 子流程内的「退出循环 (break)」只作用于子流程内部的循环,不会退出主流程的循环
  • 「调用子流程」步骤支持重试/出错时策略(子流程内部失败按该步骤的策略统一处理),但不限整体超时——子流程是完整流程段,内部步骤各自受命令级超时约束
  • 子流程不支持单步「测试运行」,请运行整个流程验证(日志中有 enter subflow / exit subflow 标记)
  • 引用按子流程 ID 记录——重命名不影响已有调用;删除被引用的子流程会校验报错

自定义指令(指令市场,callInstruction)

三方开发者可以把一段流程编排发布为自定义指令,供全平台用户在流程编排中直接引用——免安装、拖入即用,与内置标准指令同级体验。

开发者(创建指令):侧边栏「我的指令」→「新建指令」(填名称/描述/子分类/平台)→ 进入与流程编辑器一致的编排页(编排步骤、声明输入/输出变量、自带函数)→「保存草稿」→「发布」。发布后:

  • 全平台用户的流程编辑器 palette 出现**「指令市场」**分组(按子分类二级归类),可直接拖入
  • 作者自己额外有**「我的指令」**分组(草稿+已发布),可确认上架状态
  • 引用·自动更新:引用方只存指令 ID,运行时加载已发布版本——作者重新发布后,所有引用它的应用下次运行自动使用新版
  • 下架后引用方运行报「指令已下架」(编辑器校验也会提示)

使用方(引用指令):palette「指令市场」分组拖入 → 属性面板按指令声明的输入变量动态填入参(支持 {{变量}})→「输出绑定」接收返回(整体对象或按输出名取单个)。画布显示橙色 🔧 指令名 (N 入参) 卡片。

隔离语义(与子流程一致且更强):指令内部变量/函数与引用方应用完全隔离——不读应用变量、写入不泄漏、函数独立。传值只走输入/输出。指令可嵌套引用其它市场指令(深度上限 8 层)。

单步测试:「调用自定义指令」步骤支持测试运行——服务端按已发布定义顺序执行指令步骤(服务端步骤本地跑、设备步骤下发客户端),返回输出对象。

WARNING

  • 草稿指令引用后运行会报错(校验提示先发布)
  • 指令定义源码仅作者可见;市场列表只暴露名称/描述/入参出参摘要

添加备注说明(comment)

在流程中插入一条纯文字备注,记录当前指令或指令块的作用、注意问题等。画布中显示为黄色便签样式,大纲中直接显示备注文字。

仅作文字提醒和阅读参考,不参与流程执行——执行时直接跳过,零开销。备注内容支持多行,写 {{变量}} 之类的文字也不会被解析或校验。

退出循环(break)

放在循环体内,执行到该指令时立即退出当前所在的循环(嵌套时只退出最内层),继续执行循环之后的步骤。画布中显示为红色 ⛔ 退出循环 标记。

  • 常与条件判断配合:满足某条件时提前结束循环(如「已找到目标 / 已处理够 N 条」),比 breakCondition 更直观
  • 放在循环外无效果(编辑器校验会警告)
  • 放在 try/catch 内也能正常穿透(不会被当作错误捕获);在子流程内只作用于子流程内部的循环

异常捕获(try/catch)

块级错误处理:try 分支中的任一步骤失败时,跳过剩余步骤、执行 catch 分支,之后继续后续流程(不中断任务)。错误信息可写入指定变量(默认 error),catch 分支中用 {{error}} 引用(如写入输出、记录日志)。

WARNING

步骤自身配置了「出错时 = 继续 / 存失败信息到变量」的,优先按步骤策略处理,不会触发 catch。catch 分支不能为空(保存时校验)。

出错处理(onError)

每个 Action 步骤都支持「出错时」策略,控制步骤失败(含超时)时的行为:

onError 值行为
abort(默认)终止整个流程
continue跳过该步骤,继续执行后续步骤
retry重试(配合最大重试次数,默认 1 次)
setVariable把失败信息保存到变量后继续

保存失败信息到变量onError = setVariable):指定「失败信息保存到变量」的变量名后,步骤失败时**失败原因(错误消息文本)**会自动写入该变量——后续步骤可用 {{变量名}} 引用(写入任务输出、条件判断分支恢复等)。变量会自动注册到变量面板。也可在「自定义写入值」填 {{某变量}} 或固定文本覆盖默认的错误消息。

示例

  • aiTap prompt: 用户昵称, 出错时 setVariable, 变量 tapError
  • 后续条件判断: {{tapError}} !== '' → 执行恢复操作(或直接把 {{tapError}} 写入任务输出排查问题)

步骤超时(timeoutSeconds):每个步骤可配置「超时时间(秒)」(5-3600,留空=默认:AI 指令约 5 分钟、其余约 10 分钟)。超时后按「出错时」策略处理——例如 配合 setVariable 可捕获「页面卡死导致某步骤长时间无响应」的情况。注意「代码块」有自己的沙箱超时设置、「调用子流程」不限整体超时,两者不显示此配置。

WARNING

注意:{{a}} + {{b}} 会变成字符串拼接(如 "3" + "5" = "35"),不是数值运算。需要数值运算请使用「代码块」步骤。

文件操作

文件类指令全部在客户端本地执行(读取/写入都发生在运行任务的客户端机器上),路径支持 {{变量}}。适合读取批量输入、写入结果数据、管理下载文件等场景。

读取本地文件(loadFile)

读取客户端本地文件内容并存入变量,支持多种格式解析。适用于从文件批量加载关键词列表、配置等场景。

返回类型:根据 format 参数返回 array 或 string

参数

参数说明
path文件路径(支持 {{变量名}} 引用)
format解析格式:lines(每行一个,返回数组)、csv(返回对象数组)、json(返回对象/数组)、text(原始字符串)

使用方式

  1. 在变量面板声明一个 file 类型的输入变量(如 keywordFile),勾选"运行参数"
  2. 运行任务时选择本地文件,文件路径会存入该变量
  3. 在流程中添加 loadFile 步骤,path 设为 {{keywordFile}},选择 format
  4. 将结果绑定到变量(如 keywords
  5. 后续用 loop 遍历 {{keywords}}

示例流程

变量: keywordFile (file, isInput=true)
步骤:
  1. loadFile  path={ {keywordFile} }  format=lines  -> keywords
  2. loop  loopSource={ {keywords} }  loopVariable=keyword
     2.1. aiInput  输入框  { {keyword} }
     2.2. aiTap  搜索按钮
     2.3. ... 后续操作

TIP

MCP 调用时,外部 Agent 可直接传文件内容字符串(跳过 loadFile),或传文件路径(客户端机器需有该文件)。

读取 Excel 区域(excelRead)

读取 Excel 指定 Sheet 的任意区域内容,输出二维数组(每行是单元格值数组),绑定到变量供循环/代码块使用。

返回类型:数组(二维)

参数

参数说明
filePathExcel 文件路径(支持 {{变量}}
sheetNameSheet 名称(留空=第一个 Sheet)
startRow / endRow起始/结束行(1 起,含结束行;-n=倒数第 n 行,-1=最后一行)
startCol / endCol起始/结束列(字母如 A、AB,或数字 1 起;支持负数倒数)

说明:默认读取整个 Sheet;文件或 Sheet 不存在时报错。

写入 Excel 区域(excelWrite)

向 Excel 写入二维数组数据。

参数说明
filePath文件路径(不存在自动创建)
sheetName目标 Sheet(留空=Sheet1,不存在自动新建)
data二维数组(对象数组先用代码块转换,或改用「追加到 Excel」)
modeappend=写到已有数据末尾;region=从起始行列位置覆盖写入(越界自动扩展)
startRow / startColregion 模式的起始行列(1 起,支持负数倒数)

读取 Word(wordRead)

读取 Word 文档的文本内容,段落以换行分隔,绑定到变量使用。仅支持 .docx(不支持旧版 .doc)。

写入 Word(wordWrite)

.docx 写入文本(每行一个段落):append=末尾续写(保留原有内容,文件不存在自动新建);overwrite=重写整个文档。

读取 PDF(pdfRead)

提取 PDF 的文本内容(逐页提取,页间空行分隔)。扫描件(图片型 PDF)无法提取文字——请用「AI 识别文件」。

写入 PDF(pdfWrite)

向 PDF 写入文本(自动折行、自动分页,支持中英文):append=末尾新增内容页(文件不存在自动新建);overwrite=重写整个文档。

AI 识别文件(aiFileRecognize)

视觉大模型识别本地图片或 PDF 文件的内容。图片文件(png/jpg/jpeg/bmp/webp)直接识别;PDF 逐页转图识别——扫描件/图片型 PDF 也可识别(如发票、证件、截图)。

返回类型:字符串(模型按识别要求输出的内容)

参数

参数说明
filePath本地文件路径(支持 {{变量}},可配合 file 类型输入变量)
prompt识别要求:写清楚要提取什么及输出格式(如 提取发票号码、开票日期和金额,以 JSON 输出
pages仅 PDF 生效:页码范围(如 1-4),默认前 8 页、最多 20 页

示例:识别发票 → prompt 提取开票号码和开票日期,以JSON输出 → 输出绑定变量 result → 代码块 JSON.parse(vars.get("result")) 取字段。

TIP

文字版 PDF(可复制文字的)用「读取 PDF」+「LLM 对话」更省 token;AI 识别文件适合扫描件与图片。此步骤消耗 Token 余额。

上传文件(uploadFile)

上传本地文件到网页或桌面软件(web 与 Windows 桌面支持,android 不支持)。

  • web:自动识别 input[type=file] 直接设值(隐藏输入框也可),或拦截文件选择框后点击上传按钮注入文件
  • 桌面(Windows):点击上传按钮后自动操作系统文件对话框填入路径并确认

参数filePath(本地文件路径)、selector / prompt(上传按钮的定位,至少填一个)。

下载文件(downloadFile)

点击下载并保存到本地指定目录(web 与 Windows 桌面支持,android 不支持)。

  • web:先监听下载事件再点击下载按钮(避免漏事件),保存到指定目录——web 平台不弹保存对话框,由本参数直接控制保存位置(Playwright 接管下载)
  • 桌面(Windows):点击另存为/导出/下载按钮后自动操作系统保存对话框填入路径并确认(静默保存到固定目录的应用不支持)

返回类型{ path, fileName }——绑定变量后用 {{file.path}} 取值。

参数saveDir(保存目录,必填)、rename(指定文件名,缺省用网站建议名)、selector / prompt(下载按钮定位)、timeoutSec(等待下载完成,默认 180 秒)。不填选择器时仅等待下载(用于前序步骤已触发下载的场景,可能漏事件,建议填写)。目标文件已存在会直接覆盖。

处理下载对话框(downloadDialog)

保存「前序步骤触发的下载」到本地目录,本指令不点击任何按钮(web 与 Windows 桌面支持)。

  • web:接收浏览器下载并保存——验证码通过后异步触发的、甚至本步骤开始前已触发的下载都能兜住(浏览器启动时即挂持久下载监听)
  • 桌面(Windows):驱动已弹出的另存为对话框(填入路径并点保存)

返回类型{ path, fileName }典型编排(下载有验证码时):

1. AI 点击 下载按钮
2. AI 处理验证码(滑块/点选等)
3. downloadDialog  saveDir=D:\downloads  rename={ {orderId} }.pdf

本地文件管理(openFolder / listFiles / createFolder / copyFile / moveFile / deleteFile / waitFile)

对客户端本地文件/文件夹的操作,全部零 token、跨平台(含 mac):

指令说明
openFolder在资源管理器/访达中打开文件夹(路径含空格安全)
listFiles列出文件夹内文件,输出 [{name, path, size, mtime, isDir}] 数组;pattern 通配符过滤(如 *.xlsx)、recursive 递归子目录。配合循环逐个处理
createFolder创建文件夹(多级逐级创建,已存在不报错)
copyFile复制文件:targetPath 为已存在目录时复制入内保持原名,否则视为完整目标路径。已存在直接覆盖
moveFile移动/重命名(跨盘符可),路径规则同 copyFile。已存在直接覆盖
deleteFile删除文件/文件夹(文件夹需勾选 recursive)。⚠️ 不进回收站、不可恢复
waitFile轮询等待文件出现(500ms 间隔):等到输出 true、超时输出 false(不报错,常与条件分支配合:下载/导出完成后处理文件)

多实体输出

输出数据到指定实体(writeOutput)

writeOutput 步骤支持 entity 参数,可将不同类型的数据写入不同实体,在任务详情中分 Tab 展示。

参数

参数说明
data要输出的数据对象(支持 {{变量名}} 引用)
entity(可选)实体名称,如 videocommentauthor。不填则写入默认实体

配置 output_schema

在应用编辑器中配置 output_schemaentities 数组,定义多个实体:

json
{
  "entities": [
    {
      "name": "video",
      "title": "视频",
      "columns": [
        {"key": "title", "title": "标题"},
        {"key": "author", "title": "作者"}
      ]
    },
    {
      "name": "comment",
      "title": "评论",
      "columns": [
        {"key": "text", "title": "评论内容"},
        {"key": "user", "title": "评论用户"}
      ]
    }
  ]
}

示例

步骤:
  1. aiQuery  提取视频标题和作者  -> videoInfo
  2. writeOutput  entity=video  data={title: { {videoInfo.title} }, author: { {videoInfo.author} }}
  3. loop  loopSource={ {comments} }
     3.1. writeOutput  entity=comment  data={text: { {item.text} }, user: { {item.user} }}

任务详情页会展示「视频」「评论」两个 Tab,各自独立分页。

TIP

旧格式 {columns: [...]} 仍兼容,自动归入默认实体。

分布式定时调度

平台支持定时自动执行任务,支持多设备并行、cron 表达式和简单间隔两种触发方式。

创建定时调度

在左侧导航进入「定时调度」页面,点击「创建调度」:

  1. 选择应用:选择要定时执行的应用
  2. 填写参数:填写运行参数(同手动运行)
  3. 选择目标
    • Android 应用:选择一台或多台已连接的 Android 设备
    • 网页应用:选择已登录的账号(按站点过滤,如抖音应用只显示抖音账号)
    • 桌面应用:固定为本机
    • 多平台应用:账号(可选,浏览器步骤用)+ 手机设备(可选,手机步骤用);都未选则目标为本机桌面。单目标 = 一台客户端执行整个混合流程

任务目标统一注入 __target 特殊标记参数(kind: "task_target",含 deviceUdid / accounts / desktop 字段),分布式定时调度等场景可直接识别,流程内也可用 {{__target.accounts[0].accountName}} 引用目标账号。

  1. 配置调度规则:用可视化界面配置(无需了解 cron 语法)
  2. 设置重试次数:设备离线时重试次数(默认 3 次,每次间隔 5 分钟)

调度规则配置

支持两种模式二选一(顶部按钮组切换):

1. 可视化配置(默认,无需了解 cron 语法):

频率配置方式示例
每一分钟一键选择每分钟执行一次
每 N 分钟填写分钟数每 30 分钟执行一次
每小时选全天每小时 或 指定小时范围每天 9-18 点每小时执行
每天选执行时间 或 小时范围每天 9:00 执行
每周选执行时间 + 星期多选每周一、三、五 9:00 执行

2. Cron 表达式:直接编辑标准 5 段表达式(分 时 日 月 周),带语法与范围校验(支持 *、数字、A-B 范围、X/Y 步长、逗号列表),适合复杂规则:

  • */10 * * * * — 每 10 分钟
  • 0 9 * * 1-5 — 工作日每天 9:00
  • 0 9,12,18 * * * — 每天 9/12/18 点

TIP

两种模式切换不会丢配置:从「Cron 表达式」切回「可视化配置」时,若当前表达式无法用表单表示(如上面最后一种多时刻规则),表单不会自动覆写,改动任一表单项后才按表单配置覆盖。

多设备并行

一个调度可绑定多个目标(设备/账号),到点时所有目标并行执行,各自创建独立的任务实例。

设备离线处理

到点触发时如果目标设备/账号不在线:

  • 自动重试(默认 3 次,间隔 5 分钟)
  • 重试耗尽后标记为「跳过」,不影响其他目标
  • 执行记录可在调度详情中查看

执行历史

每个调度有独立的执行历史页面,记录每次触发的:

  • 触发时间
  • 目标设备/账号
  • 状态(已派发 / 重试中 / 跳过 / 失败)
  • 创建的任务实例 ID

分布式支持

  • 调度器嵌入 server 主进程,每个实例都扫描调度表
  • 通过 Redis 分布式锁保证同一调度同一时刻只有一个实例派发
  • 多 server 实例部署时自动协调,不重复执行

编辑器操作

保存与校验

  • Ctrl/Cmd + S 强制保存:即使存在校验错误也直接保存(问题步骤仍会红色高亮,保存后提示错误数量)
  • 点击「保存草稿/保存流程」时若有校验错误:弹窗列出全部问题明细,可选择**「仍要保存」**(草稿允许带错保存,发布/执行前修正即可)或返回修改;仅有警告时同样可确认后保存

拖拽编排

  • 指令之间的缝隙是固定宽度的投放热区——拖到目标位置出现蓝色横杠即可松手放入,无需等它展开
  • 画布底部常驻一行灰色**「拖拽到此处添加到最后」**空白落区,拖入即追加到流程末尾
  • 支持多选(Ctrl/Cmd + 点击)、Ctrl+C/V 复制粘贴、Ctrl+Z 撤销、Delete 删除选中
  • 复制粘贴支持主流程 ↔ 子流程之间互贴(一行或多行):复制后切换编辑目标直接粘贴即可。变量按方向智能处理——贴进子流程不搬变量(主流程变量读穿透天然可读);从子流程贴回主流程时缺失变量自动按普通变量补建(不带输入/输出标志,不影响运行表单);跨应用粘贴仍完整迁移变量与函数

附录:变量与表达式参考

变量类型

流程变量在编辑器「变量」面板中管理,分为三种类型:

类型说明示例
string字符串"高""com.xxx.aweme"
number数值050
boolean布尔值truefalse
object对象{ "author": "张三" }
array数组["张三","李四"]

输入变量isInput = true):勾选「运行参数」后,变量会在参数配置界面中显示,用户可手动填写。如 searchKeywordmaxVideos 等。

运行时变量isInput = false):流程执行过程中产生的中间变量,不暴露给用户。如 videoInfointentionResults 等。

文件变量(type: file):特殊类型,允许用户选择本地文件,文件路径自动填充到变量中,配合 loadFile 步骤使用。

变量作用域

所有变量默认在流程级别(scope: flow)生效,循环体内可以读写外层变量。循环变量(loopVariable)和 __index/__length 仅在当前循环体内可访问。

变量引用

在参数值中使用 {{变量名}} 引用变量:

语法说明
{{videoInfo.author}}引用 videoInfo 变量的 author 子字段
{{ctx.searchKeyword}}引用运行参数中的搜索关键词
{{ctx.maxVideos}}引用运行参数中的最大视频数
{{item.username}}循环中引用当前项的 username 字段
{{item.__index}}循环中引用当前索引

条件表达式

条件判断步骤和循环条件中可使用的表达式:

  • 比较运算符:===!==><>=<=
  • 逻辑运算符:&&||
  • 字符串比较:intentionLevel === "高"
  • 数值比较:totalFollowed >= 50
  • 布尔判断:alreadyProcessed === false
  • 组合条件:count < 10 && hasMore === true