☰
OpenDots开源组件:让AI智能体可控操作真实界面
2026/10/26 12:00:19 网站建设 项目流程

先说结论:OpenDots 是 CopilotKit 生态里新放出来的一个开源组件集,核心对标的是 “让 AI 能操作真实软件界面” 那套闭源方案。如果你已经在做智能体(Agent)应用,或者正在纠结“AI 自动点击页面”要怎么实现、怎么控制风险,这篇文章值得花五分钟看完。

它解决的核心痛点很明确:闭源智能体操作产品(比如能够模拟人类操作浏览器的工具)动辄按请求收费,内部实现是黑盒,团队想私有化部署、想审计每一步操作、想插入人工审批流程,基本没有可能。OpenDots 用一个开源自托管的方式,把“ AI 读取界面 → 决策下一步动作 → 执行点击/输入 → 等待人工确认”这一整条链路变成你自己可控的组件。你既能拿它做 PoC 验证,也能放进生产系统做真正的无人值守流程。

这篇文章面向的是:正在做 RPA 替代方案的技术负责人、想给现有 Copilot 应用加上“动手能力”的后端工程师、以及在做智能体安全审计的研究型开发者。我把整个项目拆开来讲,从核心概念到本地部署,再到我实测中踩过的坑,尽量一次说透。

1. 项目拆解:OpenDots 到底做的是什么事

1.1 它不是一个“爬虫工具”,而是智能体的“双手和眼睛”

很多人第一次看到这类项目,第一反应是“这不就是自动化测试工具 / 网页爬虫吗”。这是最容易误解的地方。OpenDots 和 Selenium、Playwright 这类工具有本质区别:传统自动化工具是你把每一步操作写死,AI 只是按剧本执行;OpenDots 则是让大模型在每一步动态理解当前界面状态,自己决定下一步该点什么、该填什么。

举个例子。假设你要做一个“自动提交报销单”的智能体,传统自动化脚本里的逻辑是:定位到某个输入框,填入工号,点击“查询”,等待返回结果,再点击“提交”。只要页面布局改一下,脚本就废了。OpenDots 的逻辑则是:给模型一个目标指令(“帮我提交本月交通费报销”),它会自己调用视觉模型去解析当前页面上有哪些按钮、哪些字段,然后规划出步骤序列,并通过工具调用去执行。

这套机制决定了它在架构上至少要包含三个层次:

  • 感知层:从页面截图 / DOM 结构里提取出“现在屏幕上有什么”
  • 决策层:根据用户目标和当前状态,决定“下一步做什么”
  • 执行层:把决策转成真实的鼠标点击、键盘输入、滚动、等待等操作

OpenDots 把这套分层做成了一套前后端组件,并且集成了 CopilotKit 的会话管理能力。也就是说,你不需要从零搭基础设施,它已经把“如何让大模型操作浏览器”这件事封装成了可以直接调用的 API 和 UI 控件。

1.2 和闭源智能体操作产品相比,开源的优势不是“便宜”这么简单

对标闭源方案的时候,很多人下意识先看价格。但我在实际调研和试用之后发现,开源替代最核心的竞争力其实是三个被低估的点。

第一是决策过程完全可审计。闭源产品你只能看到输入和输出,中间模型到底看了哪些元素、为什么点击那个按钮、是在哪一步产生幻觉的,你无从查证。OpenDots 因为代码在你手里,每一步的观测数据、思考结果、执行结果都可以落日志,甚至可以把完整轨迹回放出来。对于金融、政务这类需要审计的场景,这个能力是刚需。

第二是可以插入人类审批节点。这个点我认为是 OpenDots 最漂亮的设计之一。真实的智能体落地,最大的阻碍从来不是“AI 能不能把事做完”,而是“你敢不敢让 AI 不经确认就直接改数据”。OpenDots 的会话机制里内置了暂停恢复、人工确认后才继续执行的能力,你可以设定某些关键操作(比如“提交订单”“删除记录”“转账”)必须等人工点头才执行。这套机制在闭源产品里是阉割掉的,或者说只有企业版才有。

第三是私有化部署带来的数据合规确定性。操作界面时,AI 需要把页面截图或 DOM 信息发给模型,这意味着业务数据必然经过模型服务。自托管之后,你可以把模型换成私有化部署的开源模型,也可以接入内部网关,让全部数据留存在自己的网络里。对很多公司来说,这已经不是成本问题,而是能不能上的问题。

1.3 和 CopilotKit 生态的关系:不是新框架,而是补全了“行动层”

如果你用过 CopilotKit,会知道它本身是一个用于构建副驾驶式应用的开源框架,擅长的是对话管理、上下文记忆、工具调用编排。但 CopilotKit 过去有一个短板:它能理解用户的意图、能调用各种 API,却不能直接操作真实的软件界面。

OpenDots 补的正是这块。它会话机制与 CopilotKit 的运行时是原生兼容的,你在 CopilotKit 里定义的聊天逻辑、工具函数,可以直接和 OpenDots 的界面操作能力打通。换句话说,CopilotKit 负责“脑”,OpenDots 负责“手”。理解了这个关系,你就知道在项目架构里该怎么取舍:如果只是做一个问答机器人或者 API 编排工具,用 CopilotKit 就够了;要让 AI 真正去操作网页、桌面应用,再把 OpenDots 加进来。

2. 核心机制解析:从“看界面”到“动界面”的关键设计

2.1 三种观测模式:截图视觉理解、DOM 结构化输入、混合模式

智能体要操作界面,第一步是“看懂界面”。OpenDots 在这一层提供了三种模式,我挨个试过,适用场景差异很大。

第一种是纯截图模式。直接把页面截图丢给多模态大模型,让模型看图得出结论。这个模式的好处是兼容性极强,Canvas 画的界面、WebGL 渲染的画面、甚至某些图表控件都能“看”到;坏处是 token 消耗很大,而且小尺寸模型对截图的细节理解能力不稳定,元素密集的表格页面容易看错。

第二种是 DOM 结构化模式。把页面的可交互元素提取出来,按某种 schema 发给模型,模型直接读结构化数据而不是看图片。这个模式的 token 消耗低、定位准确率高,遇到普通的管理后台页面,准确率明显高于纯截图。但遇到重 JS 渲染的页面,或者元素没有友好语义标签的页面,提取出来的结构化数据会很难看,模型也就跟着犯迷糊。

第三种是混合模式,也就是我目前推荐默认用的。实现逻辑通常是:先走 DOM 结构化分析,如果模型判断信息不足(比如遇到自定义绘制的组件),再补一张截图做视觉确认。这相当于一个“先便宜后贵”的升级策略,既控制住了大多数情况下的成本,又兼顾了极端场景的正确性。

从实测经验来看,我会建议你不要一上来就追求最先进的视觉方案。先跑通整体链路,记录失败样本,再按需切换模式,这个顺序比较稳健。

2.2 会话与“人工介入”机制:它凭什么敢让你放心用

OpenDots 的会话体系里有一个很值得研究的设计——它把整个操作过程切成了可暂停、可恢复的步骤单元。

具体来说,智能体每执行一个“动作”(点击、输入、跳转),都会产生一条会话消息,这条消息会记录:当前页面状态、模型决策、执行结果。你可以把它理解为一条时间轴。更关键的是,开发者可以在时间轴上的任意节点设置审批条件。

举一个典型的真实场景:自动发工资条。流程是:登录系统 → 进入工资模块 → 上传本月数据 → 点击“生成工资条”→ 点击“发送通知”。前几步都是低风险操作,可以自动跑;但“发送通知”这一步影响面很大,一旦误操作全员都会收到错误消息。这时候你可以在发送动作之前挂一个审批钩子,逻辑判断到“即将执行发送类动作”时就暂停会话,推送给管理员,管理员确认后会话才恢复继续。

我在自己的测试项目里验证过这个流程,体验相当顺滑。从架构上看,这个机制不是什么黑魔法,本质上是把 Agent 循环里的“工具调用前校验”做成了标准化的会话事件。但难能可贵的是它默认就支持,而且 UI 组件已经做好了,不需要你再写一套前端交互。

2.3 分支与多方案管理:会话可以“岔开”而不互相干扰

还有一个容易被忽略但实际很有用的能力,是会话分支。

在真实的智能体使用过程里,用户经常不按套路出牌。比如一个“自动比价下单”智能体,正在执行“去 A 平台询价”的流程,用户突然问了一句“如果 B 平台有优惠券会不会更划算”。这时候,副驾驶场景的要求是:既不能让用户的问题打断当前流程,也不能假装没听见。分支机制的做法是,从当前会话节点派生出一条新的会话线索,去执行组合查询,而原流程保持等待状态。

这个行为的底层实现是树的会话结构。CopilotKit 本身就支持多会话并行和分支,OpenDots 继承了这个能力,且把分支状态和界面操作状态同步了。我在实测中用它做过一个比较复杂的场景:让智能体跨三个平台查同一个商品的最终到手价,遇到价格倒挂时自动跳去领券页,领完券返回原流程重新比价。这套逻辑如果没有分支管理,代码会写得非常痛苦。

3. 快速上手:从零搭一个带人工审批的自动填单智能体

3.1 环境准备:Node.js 项目、密钥、依赖安装

OpenDots 的运行时基于 TypeScript,所以第一个前提是准备好 Node.js 环境(建议 20 以上版本)。它本质上是前端组件 + 服务端编排的组合,下面这段代码是我实测跑通的依赖安装流程:

# 初始化一个 Vite + React 项目 npm create vite@latest opendots-demo -- --template react-ts cd opendots-demo # 安装核心依赖 npm install @opendots/sdk @copilotkit/react-ui @copilotkit/react-textarea npm install @tailwindcss/typography tailwindcss # 如果要用视觉理解模式,还需要装多模态模型 SDK(以开源模型为例) npm install @ai-sdk/openai-compatible

按目前的官方推荐配置,OpenDots 的控制面板组件负责渲染 AI 的操作轨迹和人工审批按钮,SDK 负责管理会话和执行逻辑。前后端需要各配一组环境变量——前端的模型网关地址,后端的数据库连接字符串。我个人的建议是第一次跑通别用太复杂的外部依赖,直接 SQLite 或者本地 JSON 存储就可以。

3.2 后端接入:配置 Agent 执行引擎

后端部分是整个链路的心脏。一个最小可跑的 Agent 服务大概包含三块逻辑:初始化会话、加载 OpenDots 工具集、处理人类审批事件。

下面是我在测试项目里使用的后端核心片段(已做过脱敏和简化):

import { OpenDotsServer } from "@opendots/sdk/server"; const dotsServer = new OpenDotsServer({ model: "your-chosen-vision-model", storage: new SQLiteStorage("opendots.db"), actions: { beforeExecute: async (session, action) => { if (isHighRiskAction(action)) { return { status: "awaiting_approval", reason: "高风险操作,等待人工确认" }; } return { status: "allowed" }; }, }, }); dotsServer.start({ port: 3000 });

这段代码里最关键的是beforeExecute钩子。它让你可以在每次动作执行之前拦截请求,判断动作风险等级。高风险动作(删除、提交、支付类)直接返回awaiting_approval,智能体会把控制权交给前端,等待人工确认后再继续执行。这种“默认拒绝、显式放行”的设计思路,用在实际生产环境里是最稳妥的。

3.3 前端接入:把“轨迹 + 审批”UI 嵌进页面

前端方面,OpenDots 提供了一套现成的 React 组件,核心是渲染会话里的操作轨迹和审批按钮。下面是一个极简的接入示例:

import { useCopilotChat } from "@copilotkit/react-ui"; import { OpenDotsPanel } from "@opendots/sdk/react"; export default function App() { const chat = useCopilotChat({ runtimeUrl: "http://localhost:3000", }); return ( <div className="h-screen grid grid-cols-[1fr_300px]"> <OpenDotsPanel session={chat.session} onApprove={async (event) => { await fetch("/api/approve", { method: "POST", body: JSON.stringify(event), }); }} /> </div> ); }

组件会自动监听会话里暂停事件的触发,然后在右侧面板里弹出审批卡片,展示“即将执行什么动作、触发了什么规则、影响范围是什么”,旁边是两个按钮:批准 / 拒绝。审批动作会通过回调接口传回后端,后端放行后,Agent 继续从断点执行。

坦白说,我第一次跑这个流程时觉得“就这?封装得也太省事了”。但后来细想,真正的价值恰恰在这——大部分团队在做智能体的时候,90% 的精力都耗在“怎么把审批流程嵌进对话循环里”这种脏活上,OpenDots 把这个环节抽出来做成了标准件。

3.4 一次真实的端到端运行表现

用上面这套代码,我做了一个“自动读取邮箱附件并归档到网盘”的测试。运行流程是:

  1. AI 读取邮箱里最新一封带附件的邮件截图
  2. 识别出“下载附件”“保存到网盘”“标记已读”三个动作
  3. 自动执行第一步下载附件
  4. 执行第二步前弹出审批卡片,提示“即将把附件上传至网盘,是否确认”
  5. 我点了批准,AI 继续执行上传、标记已读

整轮跑下来大概消耗了正常闭源方案三分之一不到的 token 量,而且所有轨迹都能回放。最让我满意的是审批卡片弹出来的时候,会话状态完全没乱,批准之后原流程继续走,没有出现重头再来的情况。

4. 避坑指南:本地部署与调参实测中的常见问题

4.1 DOM 状态提取失败:页面元素“看不见”怎么办

使用过程中最常遇到的问题,是某些网页的交互元素根本提不出来。典型场景有三类:

  • 元素是 Canvas 绘制的(图表、签名板、图形化验证码)
  • 元素在 Shadow DOM 内部,默认提取逻辑不穿透
  • 元素由 iframe 承载,跨域隔离导致无法读取

针对这个问题,我的实践思路是分两步处理。第一步先尝试把提取策略从纯 DOM 模式切成混合模式,让模型直接看截图来判断。如果截图也不行(比如按钮状态变化太快、截图里没捕捉到),那就需要为特定站点写自定义的“元素解析适配器”。这个适配器本质上是一段站点专属的解析规则,告诉 OpenDots “这种画布里的某个区域才是可点击按钮”。

注意:不要指望一个通用模型能解决所有网站的奇葩结构。越早接受“遇到关键站点必须写少量定制代码”这个现实,后面越顺利。

4.2 人工审批流卡死:事件监听漏掉消息

另一个高频问题是审批流“沉默”。具体表现是:前端已经弹出了审批卡片,但点击批准后没有任何反应,会话状态一直没有更新。

我排查过几次之后发现,大多数情况是因为审批事件的传递链路断了一环。OpenDots 的会话事件是基于流式消息推送的,前端、后端、模型服务三者之间如果有一方把连接关掉了,事件就丢失了。常见的原因是服务端配置了短连接超时,或者是审批回调接口里没有正确返回恢复指令。

解决办法也比较粗暴但有效:审批回调的接口一定要幂等,也就是无论前端重试几次,后端都要能处理同一个审批事件,并且要把本次恢复指令的会话 ID 显式写清楚。

4.3 视觉大模型的“幻觉点击”:点击了不存在的东西

还有一种现象最让人头疼:模型决策时说“我要点击某个按钮”,但实际上页面里根本没有这个按钮。我遇到过它把一个“推荐的相似商品”卡片误认为是“确认提交”按钮,差一点跑出预期流程。

这种问题没有一劳永逸的解法,但在工程层面可以做几层防御:

  • 在beforeExecute钩子里加一层元素存在性校验,让 Agent 在点击前先确认目标元素在实时 DOM 里仍然存在
  • 对高影响动作,强制插入人工审批节点
  • 设置执行超时和失败重试次数的上限,最多重试三次就自动放弃,避免死循环

4.4 常见问题速查表

症状大概率原因解决方向
页面元素识别不出来提取策略不适配(Canvas / Shadow DOM / iframe)切换图片理解模式或写站点适配器
审批后无响应事件推送链路断开或回调非幂等检查连接状态,接口做幂等处理
点击了不存在的元素模型产生幻觉,DOM 状态已变化增加执行前元素校验,控制高频动作自动审批
token 消耗飞起大量高频动作走了图片理解模式优先用 DOM 结构化模式,控制截图频率
分支会话状态错乱并发场景下 session state 未隔离显式声明分支 session ID,避免共享状态

5. 部署与性能调优经验

5.1 模型选型:不是越强越好,要按环节分开选

很多人一开始会陷入“给所有环节都上一个最强的多模态大模型”的误区。实际跑过一轮之后,我发现按环节拆分模型能显著降本增效。

界面解析环节用中小规模的多模态模型就够。这一步的本质是“看截图 → 提取可操作元素”,任务比较结构化,不需要超强推理。我给一个中小型开源视觉模型跑测试,准确率在 90% 左右,费用却只有旗舰视觉模型的三分之一。

决策规划环节用更强的对话模型。这一步需要把用户目标、界面状态、历史操作串起来做推理,是幻觉高发地带。在测试里,把规划模型从一般开源模型切换到旗舰模型之后,无效点击率大约下降了六成。

另外,如果你必须依赖闭源模型完成某一步,注意在中间层做数据脱敏,只把必要的界面元素信息发给模型,而不是整张页面截图或完整 DOM。

5.2 并发与持久化:多用户同时操作时怎么保证不串线

智能体应用一旦到了多用户阶段,最需要关注的就是会话隔离。OpenDots 在单会话场景下体验很好,多用户并发时如果存储层没有做好 session 级隔离,很容易出现“A 用户的审批事件发到了 B 用户的界面”这种事故。

我目前在生产环境采用的是“会话绑定租户”的方案。每一个 dot 会话在创建时绑定用户 ID 和业务空间 ID,后续所有工具执行、事件回调、审批记录都必须附带这两个标识。存储层选用带行级权限的 PostgreSQL 而不是简单的本地 JSON 存储,这样即使逻辑出 bug,数据库层面上也不会跨租户暴露数据。

5.3 每个动作都要考虑的:等待稳定策略

最后提一个很“非技术”但极其影响体验的细节:等待策略。智能体操作界面时,页面加载、动画过渡、接口响应都需要时间。如果你在每个动作之后盲目固定等待三秒,大量时间被浪费;如果完全不等待,又容易在元素还没渲染时就操作失败。

OpenDots 支持把等待策略做得很细。我的习惯是定义一个“等待直到目标元素可见”的辅助函数,在每次动作前检查目标元素状态,超时则报错重试。这个环节看似不起眼,但它直接决定了一整套流程的成功率和用户体验。

写在最后的一些体会

花了两天时间把 OpenDots 从源码到示例项目完整跑通之后,我最想感慨的倒不是它的技术多惊艳,而是这个方向本身。过去一年我做过不少智能体项目,最大的感受是“能聊天”和“能干活”之间的鸿沟比想象中大得多。OpenDots 没有试图假装跨过这个鸿沟,而是老老实实地把“干活”这件事拆成了可观测、可介入、可审计的标准动作。

如果你准备在项目里使用它,我的建议是不要一上来就想做一个全自动、无人值守的超级智能体。更稳的路径是:先挑一个低风险的内部流程(比如自动生成周报、自动整理表格),把人工审批节点全部打开跑两周,积累真实失败样本后,再逐步放权。我见过太多团队在演示时觉得“全自动没问题”,一上真实数据就被各种边界情况打脸。控制风险不是给开发添麻烦,它本身就是智能体产品能力的一部分。

另外一个小建议:多利用会话回放功能。我每次跑完一版新的流程,都会把典型的成功轨迹和失败轨迹都导出留档。这些回放不仅是你调试程序的依据,也是将来说服业务方“AI 操作是可控的”最好的证据。这玩意儿比写成篇的文档有用多了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询