先想象两个下午。
第一个下午,一位做 HR SaaS 的产品经理盯着自家的录入页。一张表单二十几个字段,客户一个个手敲,抱怨了半年。他想在页面角落加一个输入框,用户把简历粘进去,说一句「照这个填」,表单自己就满了。这个助手得住在网页里,跟着产品一起交付给客户。
第二个下午,另一个人开着浏览器,几个网站都登录着,桌上放着一张还没填完的表。他的要求很朴素:让 agent 把这些页面翻一遍,该点的点,该抄的抄,最后吐一份 JSON,他拿去跑脚本。浏览器是他自己的,登录状态也是他自己的。
两个需求都叫「让 AI 操作网页」,要的东西却几乎相反。前一个想把智能塞进页面,后一个想把页面变成外面能调用的东西。今年开源社区里被讨论得最多的两个项目,恰好各站一头。阿里的 page-agent,GitHub 上约 29,492 star;jackwener 的 OpenCLI,约 30,412 star。体量几乎打平,做法南辕北辙。
一个往页面里装,一个把页面往外抽
page-agent 的思路一句话能说完:它是一段跑在网页里的 JavaScript。不用浏览器扩展,不用 Python,也不用起一个 headless 浏览器。你在自己的 HTML 里加一行 script,页面上就多了一个听得懂人话的 agent。README 里的 CDN 示例是 1.12.4 版,还附了国内 npmmirror 镜像。整件事发生在你的网页里,页面自己长出了智能。
它读页面靠 DOM 文本,不截图,所以不需要多模态模型,也不需要什么特殊权限。模型由使用者自己带,主流模型都支持,本地部署的也行。示例代码里 model 写的是 qwen3.5-plus,baseURL 指向 dashscope 的兼容接口。DOM 处理和 prompt 那部分,派生自 browser-use(MIT)。
OpenCLI 是反过来的。它是一个命令行工具,JavaScript 写的,npm 包叫 @jackwener/opencli,要求 Node.js 20.18.1 以上,另有 macOS 和 Windows 的桌面版 OpenCLIApp。它要装一个 Browser Bridge 扩展,再配一个本地小 daemon,命令就能接到你已经登录好的 Chrome 上。你在终端敲一句,浏览器里真的会动。用的是你自己的 Chrome 配置,cookie、登录态、插件,全是你平时那一套。
它给了三样东西。内置的站点适配器是一样,Bilibili、知乎、小红书、Reddit、Hacker News、Twitter/X 都在名单里,命令是写死的。browser 原语是第二样,open、click、fill、extract、inspect、screenshot、network、state,任意网站都能拆开操作。第三样是让你自己写适配器,adapter init、check、test 走一遍,可以插件化,也能发到 npm 或者从 GitHub 装。
第三样东西值得多说一句。写适配器这件事听着像给开发者准备的,实际影响的是整个团队。一个人把某个内部系统摸清楚,写成一条命令,其他人不需要知道那个网站长什么样、按钮在哪、翻页参数怎么拼,敲一行就完了。知识被固定在代码里,不再散在几个人的脑子里。
一个是在页面内部生长,一个是从外部接管。方向上的差别,会顺着接入方式、稳定性、成本一路传导下去。
一行脚本的重量
第一次上手的感受,最能说明问题。
page-agent 的接入是复制粘贴级别的。一行 script,刷新,能力就在那里了。对于要把 AI 嵌进自家产品的团队,这点很实在:你交付的是一段前端代码,客户不用装东西,IT 部门也不会来问这问那。产品经理自己就能在一个测试页上试出效果,不用等排期。
OpenCLI 的第一次使用更像装一套工具。Node 版本要够,npm 装包,浏览器装扩展,daemon 起来,然后 opencli doctor 跑一遍,看哪一环没接上。它把这段做得算体面,doctor 会指出问题出在哪儿。桌面版能省掉一部分命令行的功夫,可扩展加登录态这套结构还是在那。
这不是谁更先进。想把网页当命令用,就得有个东西站在浏览器外面发号施令;想在页面里长出助手,就只能看见这一页。
边界也由此划出来。page-agent 是给客户端网页做增强的,官方说得很清楚,不是服务端自动化。它面向单个页面,想跨标签页干活,要装那个可选的 Chrome 扩展;再往外,还有个 Beta 的 MCP Server,让外部 agent 来指挥浏览器。官方列的场景挺具体:SaaS 里嵌 AI Copilot、ERP 和 CRM 后台的智能填表、用自然语言或语音帮行动不便的人操作界面、多页 agent、MCP。
OpenCLI 的主场正好相反。跨站点、批量、重复跑,本来就是它设计时盯着的事。今天抓十个页面,明天抓另外三十个,命令可以写进 shell 脚本,也可以交给 agent 当工具调用。它还有给 Claude Code 和 Cursor 用的 skill,装好之后,写代码的那个 agent 顺手就能开网页、取数据。
稳定是另一种成本
有个差别容易被忽略:同一个任务跑十次,结果的形状一样吗?
OpenCLI 的内置适配器,本质是把一个网站变成一组固定命令。输出是 JSON,成功是 {ok:true, data:…},失败是 {ok:false, error:{code, message, hint}},退出码非零,日志走 stderr。这套约定看着很工程师,对「让 agent 自己干活」却是决定性的。agent 能判断成功还是失败,能看着 code 决定重试还是换路,能把 data 直接喂给下一步。项目自己管这叫 deterministic interface,同一个命令每次行为一致。
别小看「一致」这两个字。批量任务里,一次偶发的误点可能让后面几十条数据全歪掉,而你还不知道从哪一条开始歪的。固定命令把这类风险压到很低,出错就是出错,有 code,有 hint,能重跑。
page-agent 的办法是让模型看着 DOM 决定下一步。灵活是真灵活,页面改版、按钮挪了位置,它常常还能摸过去。代价是波动,同样的指令,这次点这个,下次可能绕另一条路。每个动作过一次模型,token 成本跟着动作数走,延迟也跟着走。跑一个二十步的流程,就是二十次推理。key 放在浏览器端的话,还得琢磨怎么代理,这是工程细节,不是产品缺陷,但确实要有人去解决。
两种「聪明」不是一回事。一个把聪明花在设计的时候,把路径钉死;一个把聪明花在运行的时候,临时找路。前者省心,后者省事,省的不是同一件事。
把这几条摆在一起,大致是这样:
| page-agent | OpenCLI | |
|---|---|---|
| 形态 | 页面内 JavaScript,一行 script 引入 | CLI + 浏览器扩展 + 本地 daemon |
| 模型 | 自带 LLM,每个动作都要推理 | 内置适配器不需要模型 |
| 输出 | 页面上的操作结果 | JSON,带 ok / error 契约 |
| 范围 | 单页面增强为主,多标签要装扩展 | 跨站点、批量、可编排 |
| 适合谁 | 产品经理、前端,把 AI 塞进自家 SaaS | 要跑脚本、稳定抓数、给 agent 一套工具的人 |
这张表不是打分。它更像一张地图,标出两条路各自通向哪里。你在哪个位置,往哪边走更近,得自己看。
那就说说怎么选
两个项目的许可证都很松,page-agent 是 MIT,OpenCLI 是 Apache-2.0,商用基本不用操心。建库时间差了半年,page-agent 在 2025 年 9 月 23 日,OpenCLI 在 2026 年 3 月 14 日,最近一次推送都在 2026 年 10 月 17 日。社区体量也接近,一个两万九,一个三万出头。
有一处不一样:OpenCLI 有 265 个未关闭的 issue,page-agent 是 112 个。这个数字可以有很多解释。功能面更宽的项目,待办自然更多;也可能只是维护节奏不同。单拿它下结论不靠谱,知道一下就行。
真要选,还是回到场景。
你有一个 SaaS,想让客户在页面里说句话就把表填了,或者给后台加一个听得懂自然语言的 Copilot,甚至想用语音帮行动不便的人操作界面,那 page-agent 是顺手的。一行脚本,模型自己带,不用改部署架构,也不用说服客户装东西。
你手上有一堆重复的网页活儿,今天抓这批,明天抓那批,还得接进自己的脚本或者 agent 里,那 OpenCLI 更对路。命令固定,输出可断言,失败了有 code 和 hint 可以判断。这些在批量任务里,比「聪明」值钱。
两者也不冲突。page-agent 有 MCP Server,OpenCLI 有给 Claude Code 和 Cursor 用的 skill,一个在页面里当助手,一个在外面当工具箱,接进同一套工作流并不难。有人甚至会用 OpenCLI 去驱动一个嵌了 page-agent 的页面,各自干各自擅长的那段。
很多人第一次接触这类工具,会下意识问哪个更强。把这两个项目放在一起看,这个问题本身就不太成立。它们回答的是两个不同的问题:一个问「我的网页能不能自己长出一个助手」,一个问「我能不能把网页变成一条命令」。想清楚自己问的是哪一句,选择就不难了。



