Tactile observe-plan-act 工作流深度解析:LLM 驱动的有界执行闭环原理与实战
【免费下载链接】TactileTactile: an accessibility-first operating layer for agents.项目地址: https://gitcode.com/gh_mirrors/tactile/Tactile
Tactile 是一个无障碍优先的 Agent 操作系统层,核心是 LLM 驱动的 observe-plan-act(观察-规划-执行)工作流:Agent 通过"有界执行"闭环,用无障碍语义代替截图猜坐标,可靠地操作飞书、微信等桌面应用。本文带你完整理解这个闭环的原理、安全边界和实战用法。
为什么 Agent 需要"观察-规划-执行"闭环?
传统的 computer-use Agent 通常这样工作:
看截图 -> 猜元素 -> 预测坐标 -> 点击 -> 再看截图这条路径通用但脆弱:坐标会随窗口移动漂移,截图语义信息少,模型经常"自信地点错地方"。
Tactile 把工作方式反转成一条有监督的闭环(源码位于 skills/tactile-macos/scripts/workflows/codex_llm_workflow.py):
Observe(观察)-> Plan(LLM 规划 1 个动作)-> Act(执行)-> 再 Observe -> …每一轮循环都由一个独立的控制器进程持有全部状态:当前 UI 快照、元素索引、历史动作、剩余步数。LLM 只负责"下一小步怎么走",不拥有全局控制权——这正是"有界执行"的核心。
闭环的四个环节逐个拆解
1️⃣ Observe:先"触摸"结构,再谈视觉
每一轮循环开始时,控制器用TraversalTool重新遍历目标应用的无障碍树,得到每个元素的:
- 角色(AXButton、AXTextField、AXMenuItem…)
- 可访问名称与文本
- 位置与尺寸(frame、center)
- 层级路径(ax_path)
- 是否可被直接 AX 操作(direct_ax)
如果无障碍信息不够,还会叠加本地 OCR(系统级文本识别,同时返回文字和屏幕坐标)作为文本定位的兜底;只有当 AX 和 OCR 都不足时,才会把截图交给视觉规划。这个优先级就是 Tactile 的"操作阶梯":AX > OCR > 视觉。
2️⃣ Plan:LLM 一次只允许规划有限动作
控制器把当前状态打包成 JSON(元素列表、观察摘要、最近 5 步历史、用户指令、剩余步数),调用 LLM 生成下一步计划。规划提示词中有几条关键的"约束规则":
- 每步最多 1 个动作(可用
--max-actions-per-step放宽),防止 LLM 一口气输出"连招"; - 优先 element_id,禁止编造 id,坐标是最后手段;
- 打开弹窗、提交表单后应返回
wait,让控制器先重新观察; - 发消息类任务,必须先确认收件人可见,再输入正文。
LLM 只能从白名单动作类型中选择:click、doubleclick、rightclick、scroll、writetext、keypress、wait、finish。超出白名单的返回会被直接拒绝。
3️⃣ Act:执行前先做计划校验
在真正动鼠标之前,validate_plan会做三重把关:
- 动作数量超过上限 → 截断并告警;
- 出现白名单之外的动作类型 → 直接报错;
element_id不在当前元素索引中(即 LLM "幻觉"出来的元素)→ 拒绝执行。
也就是说,LLM 的每个决定都要通过"物理校验"才能落地,这是防幻觉的关键闸门。执行完成后,控制器还会做后输入验证:比如writetext之后重新观察,确认预期文本真的出现在输入框里;如果上一步直接 AX 点击后 UI 毫无变化(观察签名不变),会自动触发坐标回退或重新规划,而不是傻等。
4️⃣ 再 Observe:闭环靠"重新观察"驱动
执行完动作后,控制器无条件重新遍历应用 UI,进入下一轮。循环只在三种情况下退出:
- LLM 返回
finish(目标完成、受阻或需要人工介入); - 计划状态为
blocked; - 达到
--max-steps上限,运行日志记为max_steps_reached。
┌──────────── observe-plan-act 有界执行闭环 ────────────┐ │ │ │ TraversalTool 遍历 AX 树 ──┐ │ │ 本地 OCR(兜底) ──┼──> LLM 规划 1 个动作 │ │ (可选)视觉截图 ──┘ │ │ │ ▼ │ │ validate_plan 校验 ──> 执行 ──> 后验证/状态签名对比 │ │ ▲ │ │ │ └──── 重新观察,进入下一轮 ◄──┘ │ │ │ │ 出口:finish / blocked / max_steps_reached │ └────────────────────────────────────────────────────────┘有界执行:为什么"限制"反而更可靠?
"有界"(bounded)是 Tactile 工作流的设计灵魂,体现在四层边界上:
| 边界 | 机制 | 作用 |
|---|---|---|
| 步数边界 | --max-steps N(默认 20) | 卡死总迭代次数,杜绝无限循环 |
| 单步动作边界 | --max-actions-per-step | 每轮最多执行有限动作,强制每步后重新观察 |
| 动作白名单 | ALLOWED_ACTION_TYPES | LLM 只能输出受控的 UI 动作 |
| 元素存在性校验 | element_id 必须在当前索引中 | 拦截"幻觉元素",坐标必须来自最新观察 |
配合 SKILL 规范中的Bailout Rules:如果工作流反复做同一个无效动作(比如反复滚动却接近不了目标选项),就应当停止该次运行,切换到手动的observe/ocr/ax/input命令接手。"继续一个循环中的工作流"比"带着新鲜观察人工接管"风险更高。
实战:跑一次有界工作流
前置条件:macOS 已授予辅助功能与屏幕录制权限,配置TACTILE_OPENAI_API_KEY(可选TACTILE_OPENAI_BASE_URL、TACTILE_MODEL)。
第一步:用最短命令体验闭环。不带--execute时是 dry-run,只观察+规划一步,不触碰真实 UI:
bin/tactile-macos workflow "message a contact" -- --target WeChat第二步:真正执行,并加严边界。对长任务或不可逆操作(切组织+发消息),先限步、再限每步动作数,同时把运行日志写到产物目录:
artifact_dir=$(bin/tactile-macos artifact-dir) bin/tactile-macos workflow "switch org and draft a message" -- \ --target /Applications/Lark.app --execute --mode auto \ --visual-planning off --max-steps 6 --max-actions-per-step 1 \ --plan-output "$artifact_dir/lark-run.json"第三步:读懂运行日志。每次运行生成一份完整 JSON 轨迹(由 skills/tactile-macos/scripts/utils/artifacts.py 管理产物目录),包含:
final_status:finished/blocked/max_steps_reached/dry_run- 每步的
observation_sources(AX 元素数、OCR 行数、截图路径) - 每步发给 LLM 的元素数、计划内容与
execution_results
用bin/tactile-macos plan-log "$artifact_dir/lark-run.json"可以查看可读的计划日志。
模式选择:ax-rich 还是 ax-poor?
--mode auto会自动区分:飞书/Lark/Slack/浏览器等无障碍富(AX-rich)应用走语义优先路径;微信等无障碍稀疏(AX-poor)的应用会额外启用 profile 区域提示。遇到未知应用时,--capability-selection auto会在首次遍历后,让 LLM 结合可见的 AX 摘要和应用截图一次性判定走哪条路径。
高风险操作的分段策略
工作流规则对"发消息、点赞、支付、删除、账户变更"这类高风险外部动作有明确要求:把任务拆成 定位 → 草稿/展开控件 → 验证 → 提交 四段。用有界工作流完成前三段,然后从最新观察中人工核对活动窗口、目标对象与草稿状态,确认无误后再执行最后的提交动作。发送消息类任务尤其要在输入正文前验证收件人可见、提交前验证正文可见。
核心文件导航
- 闭环主逻辑(约 3200 行):skills/tactile-macos/scripts/workflows/codex_llm_workflow.py
- 入口与工具说明:skills/tactile-macos/SKILL.md
- LLM 调用配置:skills/tactile-macos/scripts/utils/llm_config.py
- 运行轨迹生成:skills/tactile-macos/scripts/utils/tactile_trace.py
- 应用专属操作指南(飞书、微信等):skills/tactile-macos/references/app-guides/
- 规划器提示词(含全部约束规则):codex_llm_workflow.py 的 build_planner_prompt
- macOS MCP 备选入口:mcps/tactile-macos-mcp/
总结:把"能力"关进"笼子"
Tactile 的 observe-plan-act 工作流给我们的启示是:给 LLM 的自主权加上物理边界,可靠性不降反升。
- 每步 1 个动作 + 强制重新观察 → 决策始终基于最新事实;
- 步数与动作白名单 → 任何一次运行都有确定的终点;
- element_id 存在性校验 + 后输入验证 → 幻觉在落地前被拦截;
- 完整的 run log → 每一步都事后可审计、可复盘。
如果你希望在自己的 Agent 自动化里获得同样稳定的桌面操作体验,可以从仓库克隆后配置该 skill 开始:
git clone https://gitcode.com/gh_mirrors/tactile/Tactile.git先跑一次 dry-run 读懂观察结构,再逐步放开--execute与步数上限,你会清晰体会到"有界"二字带来的确定感。
【免费下载链接】TactileTactile: an accessibility-first operating layer for agents.项目地址: https://gitcode.com/gh_mirrors/tactile/Tactile
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考