OpenProgram Docs

图形界面智能体#

给它一个自然语言任务。未显式选择浏览器路径时,根控制器重复选择一个有界能力:computer_use 操作本机桌面,browser_use 操作 OpenProgram 后台 Page,vm_use 操作已配置的远程虚拟机。每次能力调用中由规划器选择的参数和完整结果都会追加到下一轮模型决策的上下文。模型通过提交终态结束任务;动作数和时间限制只作为安全边界。

本机与 VM 感知使用 YOLO 组件检测(GPA-GUI-Detector)、OCR(macOS 用 Apple Vision,Linux / Windows 用 EasyOCR)和模板匹配。动作层覆盖鼠标、键盘和剪贴板。浏览器操作使用 Page 的 DOM/CDP target,不使用桌面坐标。

可用性#

每个受支持的 release 都会注册该 Program,并带上 Playwright Chromium 和 GPA detector 权重。不附带 PyTorch、OpenCV 或 EasyOCR,因此依赖这些库的桌面感知在打包产品里不可用。源码开发 checkout 仍可安装 harness 自己的依赖。开发者可以使用 editable GUI harness checkout,或替换 OCR/Browser backend 进行调试和后端开发。

怎么用#

公开入口函数名为 gui_agent,以工具形式(as_tool=True,toolset harness)注册。公开输入只有 task。规划函数和三个 *_use 函数仍会生成可追踪的子函数节点,但不会分别注册成公开工具。

命令行直接运行:

openprogram programs run gui_agent -a task="Open Firefox and go to google.com"

Programs 卡片只填写 task,不要求用户选择 surface。控制器每一轮都会读取原始任务、此前由规划器选择的能力参数和完整输出,以及当前能力可用状态,再决定下一步调用。

任务适合由当前内置浏览器 Page 完成时,仍使用同一个入口:

openprogram programs run gui_agent -a task="在不置顶窗口的情况下检查并完成当前内置浏览器表单"

受信任调用方还可以提供隐藏的控制器设置:max_steps 是动作安全上限,默认 150;max_seconds 是总耗时预算;app_name 选择组件记忆;backend 指定已有 Page backend;vm_url 启用 vm_use。surface="browser",或未指定其他 surface 时设置 backend,会选择下文的标准浏览器 Agent 路径。其他 surface 设置仍为兼容性偏好。这些设置不出现在公开函数 schema 中。

仅传 task 的执行在规划和已授权浏览器操作前不要求桌面权限。规划选择 computer_use 后,执行在发送该能力操作前检查原生权限。缺少可申请的系统授权时暂停同一任务;授权后使用保存的规划决策和能力结果继续。取消会阻止续跑,未确认结果的操作不会自动重复。缺少原生依赖仍是能力不可用,不进入权限等待。显式桌面执行保留初始权限检查。已安装默认 App 的真实权限恢复仍需验收。

显式浏览器执行#

在有效的 macOS Runtime 执行中,受信任调用方可以选择 surface="browser"。该路径使用一个标准 agent() 循环和持久、隔离的 gui_exec Python 工具,列出上下文授权的 Page,获取一次性 Page 权限并返回不透明句柄。它不会自动创建 Page,也不调用旧能力规划器。默认 backend 为 open_claude_chrome;不支持操作校验的显式 MCP backend 返回 infeasible,不会静默选择其他 backend。

此路径的 max_steps 限制 Agent 迭代次数。每次 Python 调用另有 30 秒和 100 次 broker 操作上限。allow_general=false 只提供 GUI 工具;设为 true 时还会提供标准工具,但仍受继承权限与拒绝规则约束,并排除递归 gui_agent。Python 状态在本次调用中持续保留,截图字节作为正常 Agent 图片内容返回。缺少执行身份或不支持进程隔离时拒绝执行。

浏览器 observe 返回每个元素的 ref、name、role 和 label。标签来自 aria-labelledby、aria-label 或关联的 HTML label,不根据祖先文字猜测。文本输入与 textarea 返回精确的 DOM value;contenteditable 返回 rendered innerText,并标记 value_source="inner_text"。值保留空白,写入后必须重新观察。字段精确验收要求 value 是字符串,且 value_truncated=false、value_redacted=false;ARIA 的空白归一化不能证明精确相等。每个值最多返回 8192 个 Unicode code point,同一 frame 的值合计最多占用 32768 UTF-8 字节。受限制的字段标记 value_truncated=true。密码字段及包含已知密码的普通字段不返回 value,并标记 value_redacted=true。观察文本与 ARIA 先脱敏,再限制展示长度。已知密码被截断后的前缀(至少 32 个字符)也会脱敏,不能作为验证断言。

field_context 是只读 DOM 诊断,不是字段标签,也不授权填写表单。它描述可编辑元素与最多四层祖先,包括 ID、最多六个 class、可见可编辑元素数量、直接文字,以及每层最多六个可见文本末端节点(最多检查 120 个后代)。文本末端节点与祖先的直接文字均不包含字段内容,包括 contenteditable 值内部的只读节点。文字先脱敏,再按 400 个 code point 限制展示。所有 context 共用 32768 UTF-8 JSON 字节预算;field_context_truncated=true 表示诊断不完整,预算耗尽时可以不返回 context。采用字段关联前必须检查实际结构,顺序不能单独证明关联。

native type 对普通 input 和 textarea 保持原生填写。contenteditable 在原生可编辑性检查后插入纯文本并派发 input 事件,以保留空行,不修改编辑器 CSS。如果编辑器改写了文本或 CSS 折叠了有意义的空白,操作返回 ok=false、reason_code="editable_value_mismatch" 和 observe_required=true。必须先观察当前值再决定后续操作;该结果不授权自动重复写入。

浏览器观察会从 DOM 名称、可见文字、ARIA 树和上游 MCP 快照中隐藏非空密码字段值,也检查子 frame 和开放的 shadow root。字段标签与普通输入值继续可见;观察中任何与密码相同的文字都会隐藏。动作元数据及通用浏览器的 Accessibility 动作采用相同保护,包括错误和无匹配回复。新鲜度检查在内部保留 Page 原始身份,展示脱敏不会使稳定页面失效。生成的 frame ID 和 ref 避免与已知密码发生冲突。验证检查 Page 的真实内容,不使用脱敏后的观察文字。最终结果及 completion evidence 使用相同脱敏处理。包含已知密码或其 JSON 转义形式的断言会返回 sensitive_assertion 和 passed=false,不回显断言值。

浏览器完成状态采用最近一次成功验证。后续验证被拒绝或失败时,先前的成功证据失效。Page 控制器报告成功前会重新检查文档身份,并对当前内容再次检查已记录的断言;发生导航、文档替换或确认文字消失时,需要重新验证。

模型提出最终浏览器断言,Agent 返回后由宿主对所属 Page 的当前观察状态检查。只有断言成立且本次调用不存在未确定的原语副作用,才报告成功。结果包含验证 effect 和断言证据;模型选择的断言不等于任意任务所有要求都已得到证明。脚本完成不能单独报告成功。清理会先撤销句柄,再释放 Page 租约;清理错误会阻止成功结果。清理仍可能等待正在执行的浏览器操作;执行中取消的时间上限和默认 App 验收尚未验证。

浏览器资源与人类接管#

在桌面 App 中,Agent 打开的网页保留在后台。右侧栏的 Resources 按分支列出当前会话的网页,包括子 Agent 使用的网页。继续同一分支时保持原有资源分组。即使 URL 相同,不同 Page 也保持独立;无法确定分支归属的网页显示在“未归属”中。

单击资源在聊天中查看它的图像预览。“在会话中预览”是针对同一现有 Page 的显式控件:不增加顶部标签,进入固定预览;若当前正在查看网页,则回到所属会话,使聊天预览可见。聊天预览标题栏提供持续的“固定预览 / 取消固定预览”:固定后保持当前页面;取消固定后恢复自动显示该分支最近实际操作的网页。选择资源后,即使 Agent 操作其他网页,也保持当前选择,且不抢占标签焦点。该固定控件只在聊天预览上,会话资源没有固定按钮。“隐藏”停止预览截图并保留网页。用资源行或“在会话中预览”恢复已隐藏的预览,没有单独的“显示预览”控件。“展开”放大图像预览且不改变自动或固定预览,“打开页面”把原来的 Page 显示为普通顶部标签并隐藏聊天预览。返回会话后,除非已经隐藏,否则恢复预览。这些选择按会话和分支保存。

网页标签与其预览不得同时显示。真实网页在自己的标签中保持可用,不会变暗或被遮罩阻挡。工具栏显示当前操作者,并提供“暂停 Agent,我来操作”“让 Agent 继续”“显示操作”和“操作记录”。聊天预览使用单行紧凑控件栏;空闲和已关闭显示“可直接操作”,不提供暂停或继续按钮。默认小窗为 300×198.75.拖动标题栏移动,或从任一边/角调整大小;画面比例保持联动,底层页面不被缩放。操作位置提示短暂显示,不拦截输入;记录显示操作类型和结果,不保存网页中输入的完整文字。

在真实网页中点击、输入、滚动或导航会请求暂停:停止接纳后续 Agent 输入,并请求暂停执行。仅聚焦页面或查看预览不会暂停。已经发送的动作仍可能完成。“正在暂停…”表示停止尚未确认;“已暂停”需要执行确认及状态核对。“暂停失败,请重试”表示 App 尚未确认停止,在仍连接时可用“重试暂停”;真实网页仍然可以正常使用。“让 Agent 继续”需要明确操作,并重新观察页面、检查当前权限。

关闭网页会影响所有引用同一 Page 的分支。正在使用的网页先请求停止,在确认停止前继续保留。关闭网页与隐藏预览是不同操作。连接中断或目标不可用时,最后一张图像会标注为旧画面。已保存的资源描述不会恢复 Agent 输入租约,也不会重新创建已关闭的 Page。

若 App 或 worker 重启,你尚未关闭的网页在后台恢复,不额外增加顶部标签。保留的 tab、会话与分支以及最后确认的标题和 URL 保持不变。应用为该保留 tab 创建新的活页面。先前的活句柄无效。明确关闭的网页留在“已关闭的网页”。已隐藏的预览保持隐藏,直到你选择该资源或使用“在会话中预览”。正在恢复、恢复失败或需要重新连接的行留在原分支,分别显示“正在恢复网页…”、“网页恢复失败”或“需要重新连接”,不进入通用不可用分组。恢复网页不要求“让 Agent 继续”。空闲页面仍显示“可直接操作”。新任务动作仍须在新页面上重新观察并检查当前权限。恢复会重新加载最后确认的 URL,并使用已有站点持久存储;上一进程中未保存的 DOM 与表单值不会恢复。没有保留 tab 描述的旧资源记录不会自动重建,在原分组显示“网页恢复失败”。这一有界重启恢复已经实现。

这些浏览器控制针对 OpenProgram 中的确切 Page。原生软件窗口、共享宿主桌面及虚拟机显示仍分别受到下文所述能力与输入范围限制。

自动能力执行#

未显式选择浏览器路径时,采用以下流程:

  1. plan_next_capability 接收任务、当前可用状态和完整的有序能力调用历史。
  2. 它选择 computer_use、browser_use、vm_use,或者提交一个终态。
  3. call_capability 绑定由控制器管理的 runtime 设置,并只调用本轮选中的函数。
  4. 规划器选择的参数和函数完整输出追加到 history,因此下一轮决策可以直接看到。控制器从上一项输出的 next_feedback 取得下一次调用所需的 feedback,不把它重复写进下一项 history input。
  5. 提交的终态要经过校验;没有完成证据的 success 会被记录并继续规划。

computer_use 和 vm_use 每次执行一个现有 Harness step:观察当前目标、在存在前序反馈时验证结果、规划一个动作、执行,并返回完整 step 和下一轮反馈。browser_use 每次执行一个有界的后台 Page 子任务,然后把控制权返回根循环。屏幕读取任务不走单独的预先分流。

实现统一使用 OpenProgram 的高层 agentic programming 调用。plan_next_capability、桌面规划、验证和结论通过当前 Runtime 上下文调用 llm();浏览器 Page 动作循环通过带动作工具和单次有界迭代的 agent() 执行。GUI workflow 代码不直接调用 Runtime.exec。根控制器不再嵌套一层 goal(),因为能力历史、终态提交、证据验证、超时、取消和无进展判断已经由根控制器负责;再加一层 goal 控制器会重复这些判断。

vm_use 需要兼容 OSWorld 的 HTTP endpoint。截图通过 GET /screenshot 获取,输入命令通过 POST /execute 发送。Harness 进程内的 VM 目标切换会串行执行。无论调用成功还是抛错,下一种能力执行前都会恢复原来的输入目标和截图 backend。endpoint 中的凭据和 query 值不会写入规划器的可用状态上下文。

桌面观察会包含当前前台应用和截图坐标范围。如果目标应用窗口被最小化或位于另一个 macOS Space,并且经过一次有界的 Window 菜单恢复后仍不可用,运行会以 infeasible 停止,并要求用户移动或取消最小化该窗口;它不会持续创建新窗口。

桌面坐标输入始终作用于当前前台 GUI。控制器取得准确的 macOS 进程和窗口目标后,computer_use 也可以只截取该窗口,并通过 Accessibility 执行控件支持的按压、文本赋值或滚动动作,不激活目标。控制期间,目标窗口顶部居中显示一个紧凑的深色胶囊,写着“OpenProgram 正在操作 WeChat”(系统首选语言不是中文时显示英文),并带一个缓慢闪烁的圆点。Agent 指针是一个 agent 强调色的箭头,第一次动作前停在窗口中央。成功执行动作后,它平滑移到所操作控件的中心;按压或选择会播放一次短促的波纹,并在旁边用小标签标明动作:点击、选择、输入或滚动。标签不显示输入的文字。后续同一窗口步骤会在原位恢复上一轮指针,不重播波纹,直到下一次成功动作移动它。系统开启“减弱动态效果”时,指针直接到位,不播放波纹和闪烁。胶囊和指针随窗口移动;局部遮挡不会隐藏它们,最小化或关闭窗口时不显示。正常步骤结束后,胶囊短暂显示“OpenProgram 已结束操作 WeChat”;失败或取消立即清除。提示层不接收点击;要让 agent 停下,和其他运行一样在 OpenProgram 的对话中停止。提示层不激活应用、不接收鼠标事件,也不移动系统鼠标。浏览器动作在选中的 Page 后台执行,不激活标签页、不置顶 OpenProgram 窗口,也不移动系统鼠标。根据已记录的结果,控制器可以在不同能力之间切换。

所有运行共用终态字段:status(succeeded、infeasible 或 failed)、success、reason_code、summary 和 handoff_instruction。成功与否由 runner 决定,不由 conclusion 模型决定。只有 succeeded 的 success 为 true;infeasible 和 failed 一律返回 success=false。infeasible 还保留 blocker、标记和用户接手说明。自动能力路径还包含有序能力调用历史和耗时。

max_seconds 会在每次模型或能力调用前检查,并在调用返回后再次检查。超过截止时间才返回的终态提交会被拒绝,并统一为超时失败。截止时间与步数或决策上限同时到达时,结果报告 timeout。Provider 取消采用协作式机制,因此已经发出的 provider 请求可能略晚于配置的总耗时边界才返回,但该迟到结果不会把任务变成成功。

从对话或 Run 表单发起、没有传 max_seconds 的调用,预算为 300 秒;设置 OPENPROGRAM_AGENTIC_TIMEOUT_S 可以修改默认值(0 表示不限时)。预算会作为 max_seconds 交给 agent,因此时间用完的运行会自行停止,返回 status=failed、reason_code=timeout 和已完成的能力调用历史,不再调用 conclusion 模型。运行在独立进程中执行;只有预算之后再过 20%(至少 30 秒、最多 120 秒)仍未结束,OpenProgram 才结束该进程。此时的错误 agentic subprocess timed out after N seconds 会列出运行最后报告的步骤,以及如何放宽时间。

Function 卡片直接显示这个任务结果:验证成功显示 Succeeded,任务结束但未满足请求显示 Failed,接手说明要求用户操作时显示 Needs takeover。Error 表示运行时异常或不符合契约的 GUI 结果。内部 worker 的 completed 状态不会把失败的 GUI 结果显示成 Completed。

依赖注意#

  • 产品 runtime 不安装 PyTorch 或 EasyOCR。
  • detector 模型缺失时,release capability probe 会拒绝该 artifact。
  • macOS、Linux 和 Windows x86_64 runtime 都会注册该 Program;具体桌面 backend 仍取决于 harness 自身的平台与依赖支持。
  • 运行前需要 runtime 配置好工作目录。工作流记录写入 OpenProgram 状态目录下的 gui_harness/workflows/,不再写入源码目录。

源码与 README:openprogram/programs/packages/gui_harness/,上游仓库 Fzkuji/GUI-Agent-Harness。

通过 web_use 发现 Page 不代表所选 MCP 后端能够启动。官方 MCP server 的固定版本已在 npm 缓存中时,直接从缓存启动,网络很慢或离线都不会拖慢启动。仍然无法启动或连接时,观察返回 reason_code=computer_use_backend_unavailable、availability=unavailable、实际 backend 和已关闭的会话。OpenProgram 释放失败的会话及 Page 租约,不自动改用其他后端。重新观察该 Page 即可重试,每次尝试都会重新启动后端。会话进行中 server 停止时,下一次观察会重启它。动作绝不会通过重启后的 server 发送:该动作返回 computer_use_backend_unavailable 和 observe_required=true,重新观察后再重试。

Browser Workflow 表单只显示任务和可选目标 URL。动作上限、超时与 backend 使用内部默认设置,不显示 Advanced。显式程序调用仍可使用受支持的覆盖值。

系统权限检查#

系统设置显示执行电脑上的可选桌面权限。打开页面或运行 openprogram doctor 不会申请权限。TUI 的 /doctor 和 GET /api/system/access 使用同一套检查。 未开放可选桌面权限不会阻止普通对话或升级。

macOS 托管安装通过内置的 OpenProgram 应用运行后台和 Python 子进程, 使用 OpenProgram 图标和稳定的应用标识。系统设置中应查找这个名称;安装程序不会 替用户授权。录屏和辅助功能权限分别由新启动的进程检查,使用与桌面任务相同的程序。本机系统设置中的“设置权限” 只会在用户点击后申请缺少的权限,已有授权保持不变。在系统中确认后返回页面, 页面自动重新检查。远程客户端需要在执行电脑上完成授权;其他应用的授权不能 证明 worker 已获得授权。

Linux 无图形桌面和暂不支持的 Wayland 桌面捕获会与缺少依赖分别报告。 仅存在 X11 显示配置不能证明具有访问权限。Windows 的桌面访问取决于当前会话 和目标程序,普通程序不能假定可以访问系统安全桌面或高权限目标。不会要求用户 关闭安全限制或将整个程序改为管理员运行。Linux、Windows 原生桌面验收尚未完成。

当前 macOS 开发构建没有正式生产签名。正式签名版本升级后的授权保持、首次使用 功能引导、授权后自动恢复任务尚未验证。设置系统权限不会重新执行已拒绝的操作。

系统授权#

本机桌面任务缺少系统权限时,在操作前暂停。OpenProgram 直接请求缺少的系统权限,必要时打开对应的系统设置页面。会话显示简短的暂停等待状态及“打开系统设置”文字入口;暂停的运行卡不显示权限表单、继续按钮、空结果、重试或修改操作。真正失败和取消的运行保留各自的终态。

后台保存等待中的任务,通过新启动的 OpenProgram 进程检查权限,使用与桌面任务相同的程序,避免沿用系统设置改变前保存的检查结果。检查本身不会申请权限。权限可用后,同一个任务继续一次。关闭页面不会停止检查;如果需要重启应用,启动后会再次检查保存的任务。取消任务后不会恢复。检查失败时保留等待状态,不会当作已经授权。查看旧会话本身不会启动操作或重新弹出系统授权。系统授权不会替代工具操作审批。

本地临时签名的 macOS 版本更新后,旧录屏授权可能失效,而系统开关仍显示开启。OpenProgram 会记录已安装应用成功取得录屏权限时的身份。如果之后应用身份改变且录屏检查失败,下一次本机授权操作会先更新 OpenProgram 自己的旧录屏登记,再进入系统授权流程。每个变化后的身份最多处理一次;状态检查和重连不会重置权限。使用稳定 Developer ID 签名的发行版沿用正常系统授权流程。

切换会话时,同一个等待任务的重复消息不会再次打开系统授权。你仍可主动打开系统设置。

macOS 自动化权限错误#

部分桌面命令会向 System Events 或目标应用发送 Apple Events。macOS 按目标应用分别控制“自动化”权限;录屏和辅助功能授权不代表已取得自动化权限。操作报告自动化权限拒绝时,请在执行任务的 Mac 上打开“系统设置 → 隐私与安全性 → 自动化”,检查发起请求的应用对错误中所列目标的授权。失败的操作仍保持失败;修改系统设置不会批准或重复执行该操作。其他原生命令失败会保留实际错误,不会显示为成功。

模型选择#

正文不调用模型的 Program 可以在未配置模型时执行。模型或凭据不可用时,在正文调用 Runtime 才报错;不调用模型的步骤可以执行,也不会自动选择其他 provider。

直接运行工具时,内部模型调用同样需要明确的 provider 和 model。缺失或不完整的选择不会使用全局 provider 检测或 provider 的默认模型。

从聊天执行时,GUI 和 Workflow 的内部模型调用继承当前轮次的 provider 和 model。请求 override 优先于会话选择,再使用 agent profile。该选择同样传入工具子进程。所选模型的 provider 认证仍需有效;初始化失败时保留所选模型的错误,不自动改用其他 provider。

浏览器 workflow 在选择 backend 时保留明确传入的初始 URL。官方 MCP backend 支持受取消检查约束的等待,并传递 snapshot 失败。页面恢复保留当前窗口范围,不重复执行失败的动作;确认完成的结果保留实际证据和观察到的目标。

Last updated · 2026-10-10