工作流设计经验手册

SkillMedia

Nuphus — 本地优先的 AI Agent:真实桌面执行力 + 手机第二块屏幕。Local-first AI agent with real desktop execution and dual-device real-time sync.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the 工作流设计经验手册 skill

What this skill tells your AI

The instructions your AI receives, as published by mrpulor-gh/nuphus in plugin/skills/builtin/workflow-design/SKILL.md and read by ahel’s review.

完整工作流编排能力:步骤 schema、变量语法、条件表达式、params 固化、设计模式、验证闭环、经验闭环。 L2 提示词只给阶段门禁与交互纪律;本文档是可执行的方法论全集。


〇、编排闭环总览

接收任务
  ├─ [查] ui_maps_search 检索同类经验 → 有 screen/experience 直接复用,跳过重复探索
  ├─ [探] 逐屏探索 → ui_maps_save_screen 固化布局(每屏经用户确认)
  ├─ [固] 生成 params.json + workflow.json + guide.md(参数即契约,全部有界面证据)
  ├─ [验] workflow_validate 编译校验 → workflow_run 执行 → 连续 3 次一致 + 至少一个异常路径
  └─ [馈] 跑通后 ui_maps_save_experience 提炼经验;新异常回写 params.json exceptions

任务输入形态(先识别再走闭环)

  • 用户输入带 [意图表单→工作流] 前缀,或来自 request_user_input(step_form){stage, steps}:这些阶段/子步骤是用户确认的意图骨架。表单阶段 = 流程主线分组(写入 workflow.json 保留为用户心智的阶段注释);每个子步骤 = 一条探索任务,逐条走 [探]→[固]→[设]→[验];骨架为权威输入,不得重新向用户收集流程、整体重构或丢弃补录 steps。
  • 自由对话描述:起步先问「先填意图表单(阶段+子步骤),还是我直接按您的目标探索?」——选填表 → request_user_input(input_type="step_form", default_stage=当前阶段名);选探索 → 走闭环。探索中途需用户补子步骤 → 同样弹 step_form。
  • 表单行意图是纯文本,无工具参数;工具参数(selector/坐标/窗口等)由你探索后固化进 params.json / with 字段。

一、步骤 Schema(V2,唯一真相源 src/workflow/step_schema.json

公共字段

字段必填说明
id步骤唯一标识(断点续连按 id 跳过已完成步骤)
name人类可读名称
description可选详细说明
on_error可选"abort"(默认) / "skip" / {retry:{max,backoff_ms?,backoff_multiplier?}} / {allow_codes:{codes:[...]}}
capture可选字符串:步骤输出存入变量名(无对象格式)
timeout_secs可选步骤超时秒数
do动作定义,仅下列一种 key

动作类型(do 的 13 种形态)

kind写法要点
tool{"tool":"desktop_mouse","with":{...}}with 支持 {{var}} 模板
seq{"seq":[...]}顺序容器,可嵌套
loop{"loop":{"for_each"|"repeat"|"until":..., "max":100, "do":[...]}}until=条件满足即停;max 防死循环
if{"if":{"condition":{...},"then":[...],"else":[...]}}else 可省略
call{"call":"wf-id","with":{"inputs":{...},"outputs":{...}}}inputs 传子变量;outputs 子变量名→父变量名回写
wait{"wait":"提示语","auto":[...]}auto=等待期自动执行步骤(可选)
chat{"chat":"LLM任务描述","with":{...}}LLM 决策节点(原 chat_agent)
script{"script":{"runtime":"python"|"node"|"ahk"|"pwsh","code":"...","cwd":"?"}}code 支持 {{var}} 替换
assert{"assert":{"condition":{...},"message":"?"}}on_error=skip 时变非阻断校验
mcp{"mcp":{"server":"key","tool":"name","with":{...}}}server 对应 servers.yaml
sleep{"sleep":N}秒,0.1–3600
break{"break":true}跳出当前循环
continue{"continue":true}跳过当前迭代

chat 步骤 with(LLM 决策配置)

agent_id(ChatAgentConfig ID)/ screenshot(执行前截图注入)/ tools(白名单)/ knowledge(知识库路径)/ model / temperature / max_tokens / system_prompt / persona / goal / constraints / requirements / max_iterations(ReAct 最大轮数,与 max_steps 语义重叠,统一用 max_iterations

容器 on_error

seq / loop / if 容器同样支持 on_error;子步骤失败且容器设置了 skip 时继续执行容器内后续步骤。


二、变量与模板语法

三套引用,边界必须分清

写法语义适用
{{var}}模板替换。整串时保留原始类型(数字/布尔/对象不字符串化);内嵌文本(如 "x={{var}}px")时字符串化with 参数值、script code
{{var | get "f"}} / {{var | json "k"}} / {{var | len}} / {{ENV:HOME}} / {{var | default "v"}}管道表达式同上
{params.window.url}单花括号,仅整串引用 params.json 字段,返回原始类型;点号路径下钻引用固化参数
{ "var": "name" }对象形式变量引用(VarRef),支持点号路径 { "var": "coords.x" }条件表达式、loop.for_each.items

坑:坐标字段若内嵌 {{x}} 会字符串化,务必整串引用或用 | get 下钻保持数字类型。

变量池来源

workflow_run(inputs) 注入 → params.json({params.x} 兑现)→ 各步骤 capture 写入。子工作流有独立变量池,靠 call.with.inputs/outputs 跨池传递。


三、条件表达式(Condition,12 种)

二元([VarRef, 值] 两元数组):equals / not_equals / contains / starts_with / regex / gt / lt / gte / lte 一元:not_empty / empty 恒真:always

{ "if": { "condition": { "equals": [ { "var": "login_status" }, "LOGGED_IN" ] }, "then": [...] } }

四、params.json 固化规范

字段内容
workflow_id工作流唯一标识
window尺寸 / URL / 标题模式(窗口尺寸必须固化,W2)
login_detection登录态判定特征
regions区域定义 + 定位特征(每参数有界面证据)
navigation_graph屏间跳转关系
exceptions异常路径 + 降级策略(探索中异常即时记录,W4)

模板骨架:

{
  "workflow_id": "demo-flow",
  "window": { "title_pattern": "App 标题", "width": 1280, "height": 800 },
  "login_detection": { "indicator": ["登录", "Sign in"] },
  "regions": [{ "name": "chat-list", "rect": { "x": 0, "y": 100, "w": 300, "h": 600 }, "anchor": { "type": "text", "value": "会话" } }],
  "navigation_graph": { "chat-list": { "to": ["chat-window"], "trigger": "click-contact" } },
  "exceptions": [{ "condition": "登录弹窗", "fallback": "wait 用户介入" }]
}

五、设计模式库

模式 A:登录态检测守卫

{ "id": "guard", "name": "登录保障", "do": { "seq": [
  { "id": "check", "name": "判断登录态",
    "do": { "chat": "根据 login_detection 特征判断是否已登录", "with": {
      "agent_id": "login-checker", "screenshot": true,
      "requirements": ["只输出 LOGGED_IN 或 LOGIN_REQUIRED"] } },
    "capture": "login_status" },
  { "id": "branch", "name": "按登录态分支",
    "do": { "if": {
      "condition": { "equals": [ { "var": "login_status" }, "LOGIN_REQUIRED" ] },
      "then": [
        { "id": "manual", "name": "手动登录", "do": { "wait": "请完成登录后点击继续" } }
      ],
      "else": [] } } }
] } }

要点:语义判断(chat+screenshot)而非文案匹配;登录动作交用户,不碰凭据。

模式 B:for_each 遍历

{ "id": "tour", "name": "遍历", "do": { "loop": {
  "for_each": { "items": { "var": "panels" }, "as": "p" },
  "max": 100,
  "do": [ { "id": "hit", "name": "点击", "do": { "tool": "desktop_mouse",
    "with": { "action": "click", "x": "{{p | get \"ix\"}}", "y": "{{p | get \"iy\"}}" } } } ]
} } }

模式 C:表单提交 + 结果验证

seq: 提交
├─ 填写 + 提交(desktop_input 输入+发送一次调用,不拆分)
├─ browser_wait_for(结果页元素)
├─ assert: 成功标志存在
└─ if: 失败 → screenshot → chat 分析 → 重试或终止

模式 D:多窗口操作

每次操作前 desktop_windows_list 重取 hwnd(hwnd 会变)→ activate → 操作。

模式 E:大工作流拆分

单层 >15 步或嵌套 >3 层 → 拆子工作流。主文件含 call 步骤,子工作流 JSON 同目录。用 with.outputs 回传结果。

模式 F:SPA 搜索框提交(优先级从高到低)

  1. browser_snapshot 找 @eN ref → click
  2. 无 ref → browser_screenshot → OCR 找按钮坐标 → JS 模拟点击
  3. 都不行 → browser_evaluate 触发 form.submit()(最后手段)

模式 G:验证码/滑块

desktop_mouse_drag 起点→终点;无法自动处理 → wait 用户介入并标记 exceptions。


六、验证闭环方法论

workflow_validate(编译校验:步骤合法性/工具名/必填/变量引用/call 环)
  → 干净环境 workflow_run(第 1 次:探路,记录偏差)
  → 分析异常 → 修正 params / workflow(设计缺陷才改文件;运行时阻塞就地解决)
  → 重跑(同 id 断点续连,禁新建复制)→ 连续 3 次结果一致
  → 至少触发一个异常路径验证降级

验收:跑通 ∧ 3 次一致 ∧ 异常路径生效 ∧ 降级不丢数据不重复提交 ∧ 无敏感数据残留。

运行时故障恢复:失败 → 识别阻塞(验证码/弹窗/登录态/网络)→ 就地解决(browser_/desktop_ 同会话,状态保留)→ 同 id 续跑。同一步骤同阻塞连续 3 次失败 → 停止,用 completed_steps 汇报。


七、经验检索 / 提炼

两级检索

  1. 骨架:ui_maps_search(query="微信 im") → 有哪些 screen / experience
  2. 详情:ui_maps_search(query="微信", screen_name="chat-list") → 完整 regions + 关联经验

什么值得存(存「法」不存「案」)

  • ✅ 非显而易见操作序列 / 跨应用可复用模式 / 踩过的坑 / 特殊定位技巧
  • ❌ 常规操作(browser_navigate)/ 一次性案例 / 提示词已覆盖内容

summary 写法

做什么 → 怎么做 → 为什么 → 跨应用适用性(非传统思路要标注省了几步)。


八、工具使用要点

场景首选备选
定位网页元素browser_snapshot → @eN refscreenshot + OCR
桌面布局解析Vision 全窗口语义分析perceive 精确坐标
定位桌面文字Vision 划定功能区desktop_find_text(需字库)
等待加载browser_wait_for(selector)system_sleep(不得已)
验证状态snapshot + chat 语义判断extract 文本匹配
查经验ui_maps_search 两级检索Read ui-maps JSON

坐标体系desktop_mouse 一律用屏幕绝对坐标;perceive 结果为客户区坐标时手动加 screen_x/screen_y 偏移。

输入desktop_input 输入+发送一次调用;普通文本直接输入,>500 字用 clipboard 并事后 clean;敏感内容禁用 clipboard。


九、陷阱清单

陷阱正确做法
跳过布局解析直接找元素(W1)逐屏 vision+perceive 解析,保存 ui-maps
窗口尺寸未固化(W2)params.json window 字段固化
探索阶段写步骤(W3)核心路径手动跑通后才设计
if contains 文案做登录检测chat 语义判断 + screenshot
忘记 SPA 状态残留新流程前重置(about:blank / resize 固化尺寸)
tooltip OCR 截到其他窗口先 desktop_window_info 拿客户区边界,截图限域
重试重复提交表单重试前检测状态,已完成步骤跳过
纯色/低纹理模板匹配误报find_image 模板需含纹理;用 region 限定加速
动态 UI 区匹配失败识别为动态区域,改用文本/语义定位

Signals

GitHub stars
65
Forks
13
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
workflow-design-mrpulor-gh
Source
github.com/mrpulor-gh/nuphus