能搬进标签页的任务,是那些不需要伸手到这四扇门之外的任务;值得搬的,更少。
一个 Agent 能不能住进浏览器,看它要做的事会不会伸到四扇门之外:模型、文件、进程、网络。前三扇今天都有现成的东西能推开,只是各带条件。第四扇是网络,浏览器只开了一条缝:大多数给人看的网页读不了,TCP 连不了。所以“纯网页 Agent”在工程上是本机计算加一个很薄的出口;任务一旦要从出口之外拿东西(git、ssh、数据库、普通网页、无人值守),就搬不进来。能不能之外还有值不值:站得住的是“执行在浏览器、模型在云”,把模型也搬进标签页,覆盖面和能力都还不够。
showDirectoryPicker 只有 Chromium 有(Chrome 86 起),Firefox 和 Safari 没有,只剩 OPFS,那不是你的磁盘。我的页面只读导入,上限 300 个文件、4MB,改动先留在内存。两个运行时里,Agent 都是先用页面自带沙箱跑测试,撞上一个报错,才想起改用真 shell;任务描述里没人提 Bash。限制它的不是会不会用工具,是页面有没有把真工具摆出来。
我最开始担心的不是速度。一个纯网页的 Agent 去改你本地目录里的项目,听上去该被浏览器的安全模型卡死:网页凭什么读你的磁盘,凭什么跑 shell,凭什么联网装依赖?
10 月 14 日到 20 日,我做了两个页面来拆这个怀疑。它们共用同一个 Claude Code 风格的 Agent 外壳:读写文件,改前确认,跑测试,改完要自己验证。区别只在 Bash 工具背后的运行时。第一个页面用 StackBlitz 的 WebContainers,第二个用开源的 Wasmer,各自只多了一百多行代码。模型是 BigModel 的 glm-5.3(那几天它的接口还能被网页直接调,见 § 02)。
结论先说:安全机制没有把它卡死。浏览器给了文件一把钥匙,给了进程一把钥匙,只是每把都带条件。真正卡住它的是第四样东西,网络。
先给答案,再讲怎么量的。“证据”一列:实测是我或我派的会话亲手跑过,文档是读官方文档得到,推断是没测、由前两类推出来的。
| 任务 | 能在标签页里做吗 | 证据 |
|---|---|---|
| 读你的项目目录,改完写回 | Chromium 能;Firefox、Safari 退化成内存里的空工作区 | 文档。授权、读取、写回的整条路径我没有自动化跑过(系统弹窗点不了) |
| 修纯 JS 项目里的 bug,跑单元测试 | 能 | 实测,两个运行时各一次 glm-5.3 任务;10 月 28 日又用本机 gemma4 各跑两遍,宿主机 Node 复核 5/5 |
| 装 npm 依赖再跑测试 | WebContainers 能;Wasmer 要你自己提供中继,且只能用 pnpm | 实测 |
| 调 GitHub、npm、PyPI、Wikipedia 的 API | 能 | 实测(CORS 放行) |
| 读一篇普通新闻或文档网页 | 多数不能 | 实测,31 个 URL 里 19 个没有放行头 |
| git commit、push | 不能,两个运行时里都没有 git | 实测 |
| ssh、连数据库 | 不能 | 文档加推断:浏览器没有 TCP |
| 跑 Python 脚本 | Wasmer 能(Python 3.13,首次约 22 秒);WebContainers 里只有 RustPython alpha | 实测;科学计算库没测 |
| 无人值守,跑一整夜 | 不能,标签页一关就停;后台超过 5 分钟还可能被冻结 | 文档(Chrome 133 的冻结规则)加推断,没实测 |
| 几千个文件、要原生编译的工程 | 不能 | 页面导入上限 300 个文件、4MB;两个运行时都没有 gcc |
每一行最后都落在四扇门里的某一扇上,下面一扇一扇讲。
Agent 在浏览器里干活,想的却是远处的模型。第一个问题是页面能不能直接调它。
我用 curl 冒充一个来自 roam.xiaopingfeng.com 的页面,对 14 个模型接口各发一次预检请求,再发一个带假 key 的 POST,看错误响应有没有允许来源的头。脚本和原始输出放在这个文本文件里。10 月 20 日,14 个预检全部放行;10 月 28 日我用同一个脚本复测,有一处变了,其余两处细节也值得记。
变了的是 BigModel。open.bigmodel.cn 的 /chat/completions 预检现在返回 200,却不带任何 Access-Control-Allow-* 头,只带 authorization 或只带 content-type 的预检也一样;连测三次都如此,Chrome 里带 JSON 的 POST 直接报 “Failed to fetch”。同一站的 /models 仍然放行,国际站 api.z.ai 的两条路径也放行。10 月 15 日到 20 日我所有的 BigModel 真实模型测试都是通的,所以这是这一周里变的;我没有联系对方确认是临时还是永久。我两个页面的配置示例写的恰好是 BigModel,现在多半调不通。意思很直接:模型这扇门,开关在接口方手里,他们改一行网关配置,纯网页 Agent 就连不上了,用户自带 Key 的页面最好同时支持几家。
Anthropic 的接口,预检里不声明 anthropic-dangerous-direct-browser-access 这个头,就不返回允许来源;声明之后返回通配,假 key 的 401 也带着头。这个头名自己把话说完了:他们默许你这么干,但要你亲口承认风险。火山方舟的预检过了,错误响应却没带 CORS 头,页面发一个错 key,浏览器只报一个不透明的网络错误,读不到 401,调试这类接口最费劲。其余十一个,有的回显我的域名,有的回 *。
放行只回答了能不能调。页面把 API key 存在这个域名的 localStorage 里,请求从浏览器直接发给你填的地址,不经过站点;也就是说,能在这个域名下执行脚本的任何东西,一个被投毒的依赖,一个扩展,都读得到它。
本地模型是另一回事。WebLLM 在浏览器里推理,页面代码按 4–8k 上下文给它限了 14 个核心工具;Ollama 默认不让别的域名调,要在服务端设 OLLAMA_ORIGINS。10 月 15 日的实测里,qwen2.5:7b 能守住动作格式,却会在动作后面自己编一段“观察结果”,没验证就说完成,贪吃蛇做不出来;gemma4:31b 44 秒做出了能玩的版本;glm-5.3 默认的最深推理档做同一个贪吃蛇要 246 秒,调成 low 是 45 秒。
所以这扇门的条件是:你愿意把代码片段发给某个模型 API,并且接口方没有关掉浏览器直连,或者本机有 30B 级的模型。WebLLM 的真实推理我没有跑过。
浏览器让网页读写你的真实磁盘,靠的是 File System Access API 里的 showDirectoryPicker。规矩很具体:只在 HTTPS 下可用;必须由用户点击这类动作触发;你选哪个目录,页面就只拿到哪个目录;选到浏览器认为太敏感的目录会被拒(Chrome 的文档举的例子是 Windows 和 macOS 的系统库目录);写入要另外弹一次授权,同一站点的标签页全关之后,授权也跟着丢。
所以我最初的怀疑,在文件这一格上是错的。这套机制就是为这件事设计的。
卡点在别处:兼容数据里 showDirectoryPicker 只有 Chrome 86 起,Firefox 和 Safari 都是不支持。后两者有 OPFS(Firefox 111、Safari 15.2 起),但那是浏览器给站点划的私有空间,不是你桌面上的文件夹。换句话说,“对你本地的项目工作”只在 Chromium 里成立,在别的浏览器里退化成一个从零开始的内存工作区。
我的页面还做了两个收窄。打开文件夹时只读导入,最多 300 个文件、单个 200KB、总共 4MB,node_modules、.git、dist 这些目录直接跳过;Agent 的改动先留在内存里,你输入 /save 才会申请写权限落盘。两个运行时里的文件系统本来也是虚拟的,所以每条 Bash 命令前后,页面都要把工作区同步进去、再把被改过的文本文件同步回来。
这一格我有一件事没验证:授权、读取、写回的整条路径,我没有自动化跑过,因为那个选择框是系统弹窗。
这一扇最难,变化也最快。
门槛先说清楚。在浏览器里跑一个像样的运行时,要多线程,要多线程就要 SharedArrayBuffer,而它只给跨源隔离的页面用:响应头要带 Cross-Origin-Opener-Policy: same-origin,再配 Cross-Origin-Embedder-Policy 的 require-corp 或 credentialless(见 MDN)。对一个静态站意味着给这个页面的路径单独配响应头:roam 部署在 Cloudflare Pages,我在 _headers 里只对两个路径开,别的页面不动。
我选了 credentialless,因为 require-corp 会拦掉预览里没带 CORP 头的第三方图片(这是另一个会话测出来的)。代价写在兼容数据里:credentialless 是 Chrome 96、Firefox 119 起,Safari 不支持。WebContainers 官方自己也说,桌面 Chromium 开箱即用,Safari 和 Firefox 还在 beta。进程这一扇,实际上也是 Chromium 的。
两个运行时放在一起:
| WebContainers | Wasmer | |
|---|---|---|
| 运行时在哪 | StackBlitz 托管,从它的域名加载,闭源 | SDK 随页面同源发出(约 5MB),bash、Node 等包首次从 Wasmer 的包仓库下载 |
| 里面是什么 | Node 22、npm | bash、Node 24(Edge.js)、pnpm,Python 3.13 按需加载 |
| 冷启动 | 27.2 秒(1 个样本);另一些样本 7 到 8 秒;线上我测到 15.1 秒 | 27 到 38 秒(约 89MB);Python 另约 22 秒 |
| 暖启动 | 0.34 到 0.68 秒 | 0.66 秒 |
| 联网装包 | 开箱即用 | 要自己提供 WISP 中继,只能用 pnpm |
| 真实 glm-5.3 修 cart | 29 秒 | 61 秒,含 34.4 秒冷启动 |
这些数字的样本都很小,WebContainers 那一列冷启动只有一两个,别当基准。cart 是个三个 bug 的小项目(reduce 缺初值、价格没补零、折扣返回的是折扣额),WebContainers 那一列来自另一个 Claude Code 会话的报告。
比数字更有意思的是 Agent 的行为。两次真实任务里,它都是先调页面自带沙箱的 Test,得到一句 test is not a function,读了测试文件,然后自己改用 Bash 去跑 node --test。那个报错是页面的 bug:我的沙箱对标准写法 import test from 'node:test' 返回了一个没有默认导出的对象。任务描述里没提 Bash;系统提示里有这个工具,但它是撞上报错之后才去用的。它换了,修好三处,重跑,5/5 通过。我把 Wasmer 那次的工作区导出,在真实 Node 里跑原测试,5/5,测试文件没被改动。
另一面是,每个运行时都有一串坑,最后都变成工具说明里的一句话,和一个守卫。Wasmer 这边我踩到的:
node --test 默认模式报“serializer payload is no longer available”,要用 --test-isolation=none,页面现在自动替它加上。node x.js | tail 得到空输出,echo hi | cat 却正常。工具说明里写着“node 的输出别接管道”。npm install 失败,报 https 协议不支持,只能用 pnpm,还要一个 .npmrc。timeout_ms 会失灵:SDK 自带的超时要等阻塞的 guest 调用(比如 sleep 30)返回才生效,我限 3 秒的命令曾经 30 秒才回来。页面现在自己计时、到点强杀,这是跑下面那批任务时发现的,已修。两个运行时共同的缺口更值得记:没有 git,没有 grep、sed、awk、find。文件搜索还有页面里的 Grep 和 Glob 兜底,git commit 就没有替代品了。WebContainers 里原生模块能装上、却在 require 时报 ERR_DLOPEN_DISABLED,装得上不等于用得了。
我后来把这些“能不能”写成了十一个任务,用同一个接口(boot / put / exec)分别接到 WebContainers、Wasmer,和一个临时部署的 Cloudflare Sandbox 上跑。浏览器两格跑的是线上页面里真实的 Bash 工具;云端一格是官方最小示例默认的 lite 实例,我把镜像换成了带 git、Python 和编译工具的 Debian、打开了出站网络,测完把 Worker、容器应用和镜像都删了。每格只跑了一次,不是基准;任务脚本、适配器和原始结果在这个文本文件里。
| 任务 | WebContainers | Wasmer | 云端 lite |
|---|---|---|---|
| node:test 红到绿(3 个 bug) | ✓ | ✓ | ✓ |
| 装纯 JS 依赖再 require | ✓ npm | ✓ pnpm,要中继 | ✓ |
| git init / commit / log | ✗ 没有 git | ✗ 没有 git | ✓ |
| grep / sed / awk / find | ✗ 全没有 | ✗ 全没有 | ✓ |
| 装原生模块(better-sqlite3)并调用 | ✗ 装得上,加载被禁 | ✗ 没有可加载的二进制 | ✓ 约 37 秒 |
| Python 跑脚本、import sqlite3 | ✗ 有 python3,缺 _sqlite3 | ✓ Python 3.13 | ✓ Python 3.11 |
| 出站 HTTPS 到没开 CORS 的站点 | ✗ socket 被关 | ✓ 经自备中继 | ✓ |
| node 当管道的上游 | ✓ | ✗ 输出为空 | ✓ |
| 超时强杀:node 空转 30 秒,限 3 秒 | ✓ 3.1 秒 | ✓ 3.8 秒 | ✓ 3.1 秒 |
超时强杀:shell 的 sleep 30 | ✗ jsh 里没有 sleep | ✓ 3.0 秒 | ✓ 3.3 秒 |
| 3 秒空转的迭代次数 | 1.2 亿 | 1800 万 | 160 万 |
| 冷启动 | 7.5–7.7 秒 | 27–34 秒 | 9–13 秒 |
暖命令(echo) | 约 105 毫秒 | 约 58 毫秒 | 150–615 毫秒 |
浏览器里的两个运行时和云端,在“跑 Node、跑测试、装纯 JS 包”这一层没有区别,红绿测试三家都是改前 4 败 1 过、改后 5 过。差在工具链:git、grep 这一类、原生模块,云端都有,浏览器里两家都没有。这和 § 01 判定表里那几行是同一回事,现在每一行都有同一批任务跑出来的结果。
两处我没想到。一是出站网络:WebContainers 里 fetch('https://example.com') 直接失败,Wasmer 靠我自备的中继反而通了,云端本来就通;和 § 05 说的一致,出口在谁手里,谁就决定能读什么。二是算力:同一个 3 秒空转,WebContainers 跑了约 1.2 亿次,Wasmer 约 1800 万,云端 lite 约 160 万。浏览器里的 Node 用的是你自己机器的 CPU,比官方最小示例默认的那一档云端实例快得多;Wasmer 比 WebContainers 慢约 7 倍,原因我没查。云端这一格别读成“云端都这么慢”,我没试更大的实例。冷启动的次序也反过来:云端 9 到 13 秒,比 Wasmer 的 27 到 34 秒快,但每条命令要多一次网络往返,暖命令 150 到 615 毫秒,浏览器里是 58 到 105 毫秒。
“计算在你本机”这件事,我也量了一次,没有只信文档:让两个运行时各跑一个 16 秒的空转循环,同时每两秒用 top 采一次样,把名字以浏览器应用名开头的进程(主进程、各个渲染进程)的 CPU 加起来。空闲时合计 12 到 23%,循环期间升到 53 到 67%,结束后回落到 13 到 32%;循环期间有一个渲染进程单独占了约 40 到 49%。命令如果是在远端跑的,本机不会有这个起伏。这个测量有噪声:第一次试跑时 WebContainers 的空闲基线就有 100% 以上,所以我重跑了一次,这里写的是重跑的结果,每个运行时只有这一次。它只能说明这些循环的计算发生在这台机器上,我没有抓包去证明没有别的流量。
还有一个坑,是关掉跨源隔离之后才看到的。我的页面在没有响应头时会把 Bash 工具藏起来,但直接用 Wasmer 的 SDK,页面没隔离它也不报错:run() 返回成功、退出码 0、标准输出和标准错误都是空的,用时 22 毫秒,命令根本没有跑;同样的代码在隔离的页面里输出了 hi。拿它做集成测试的人,会得到一个看起来全绿的空结果。
网络分两层。第一层是 HTTP,浏览器的规矩是 CORS:页面只能读那些在响应头里写明“允许你这个来源读”的站点。
我同样用 curl 冒充页面,测了 31 个公开 URL(原始输出在同一个文本文件里),挑的偏开发者常去的站点,不是随机抽样。
| 结果 | 数量 | 例子 |
|---|---|---|
| 放行 | 11 | GitHub raw、GitHub API、npm registry、PyPI JSON、jsDelivr、unpkg、Wikipedia REST、Hacker News API、Hugging Face API |
| 只放行自己的域名 | 1 | 大麦网 |
| 没有放行头 | 19 | github.com 网页、Wikipedia 网页、MDN、Python 文档、arXiv、BBC、知乎、掘金、36氪、百度、豆瓣;Reddit、Stack Overflow、纽约时报直接返回 403 |
模式很清楚:给机器读的端点基本放行,给人看的页面基本不放行。按我划的性质拆开:12 个给机器读的端点里 10 个放行,19 个给人看的页面里只有 1 个。同一个 Hugging Face,API 放行,模型页不放行;同一个 Wikipedia,REST 接口放行,词条页不放行。另一个会话在 WebContainers 里看到同样的事:容器里的 curl 和 fetch 读大麦、秀动都失败,npm registry 通。
对 Agent 来说,后果是它能调 API、读文档仓库、拉包,但大多数你会让它“去网上查一下”的页面,它读不到。我的页面里有个 WebFetch 工具,默认每个域名先问你,只读开放了 CORS 的站点;你可以手动打开一个阅读代理(r.jina.ai)绕过去,代价是代理会看到你要读的 URL。
第二层是 TCP,浏览器根本没有。npm 装包、ssh、连数据库,全都要 TCP。两个运行时的办法不同:WebContainers 靠 StackBlitz 的代理服务;Wasmer 要你自己提供一个 WISP 中继,一个把 WebSocket 转成 TCP 的小服务。
我在这上面花了不少时间。没有中继时,npm install 一直卡着,60 秒没有任何输出,也没有报错。起了本机的中继,pnpm add 还是失败,guest 里只有一个 ECONNRESET。最后在中继的日志里才找到那一行:refusing to create a stream。原因是我这台机器的 DNS 返回的是 fake-IP(198.18.x.x,代理软件的常见做法),而中继默认把这个网段当私网拒绝。加上 allow_private_ips 之后,pnpm add is-odd 4.4 秒,pnpm add -D mocha@10 约 12 秒,mocha 先 2 过 3 败,改完代码 5 过。TLS 是在 guest 里完成的,我用 tls.connect 验证过握手,协商出 TLSv1.2;所以中继看到的是目标主机、端口和密文。
这里有三件事要摊开。中继是个服务端,“纯网页”到这一步就不纯了。放开私网段的中继,等于在本机开了一个可以到内网的跳板,我没有验证它会不会按来源页面拦截,所以只在测试时开,用完就关。还有,WISP 的客户端库 @mercuryworkshop/wisp-js 的许可是 AGPL-3.0,所以我没有把它放进仓库,页面只在你配置了中继之后才从 jsDelivr 加载它。这样处理够不够,我没有请人确认过。
浏览器厂商不是没想过:Chrome 有一个 Direct Sockets API,让页面开 TCP 和 UDP,但只给 Isolated Web Apps,一种要安装、带严格内容安全策略的隔离应用,不给普通网页。2024 年提交发布意向时,Gecko 没表态,WebKit 没有信号;2026 年的最新状态我没有核。
问这个问题的人通常想知道有没有标准。浏览器这一层没有。有标准的是底下几块:文件 API(还不是 Baseline)、跨源隔离、WebAssembly。往上,每个运行时都是一家公司的产品:
@webcontainer/api 包标 MIT,只有 35KB,是个客户端壳。boot() 会插一个隐藏的 iframe,指向 stackblitz.com,真正的运行时从那里加载。GitHub 上的 webcontainer-core 仓库,README 自己写着是个 issue 汇总处。生产环境的商业使用要买授权,原型和 POC 不用;自托管只在企业版里。我去读这些,是因为 MIT 这个标签很容易让人以为整套都开源。行业里用得最多的 Agent 沙箱不在浏览器里。2026 年 5 月一份 Agent 沙箱清单把方案分成托管沙箱(E2B 和 Vercel Sandbox 用 Firecracker 微虚拟机,Cloudflare 是 V8 隔离加容器)、本机操作系统级沙箱(macOS 的 Seatbelt、Linux 的 Landlock、bubblewrap),以及内置在 Agent 里的沙箱:Codex CLI、Claude Code 都是这一类。E2B 是 Apache-2.0,约 1.4 万星。浏览器路线在这张图里是一小块,卖点只有两个:零安装,代码不离开你的机器(模型 API 除外)。
我另一篇文章量过服务端这一头对 Agent 的开放程度:哪家服务真正做到了 Agent native。两篇放一起,我的读法是:Agent 能走多远,要看对面有没有给机器留一条不用问人的路。服务端缺的是这条路,浏览器缺的也是。
前六节量的是能不能。能不能和值不值是两件事:一个东西可以跑得通,却没人愿意为它付钱。这一节问第二件。
我分三路去查:产品和市场,端侧模型和浏览器平台,标准与风险(含反面论证)。关键数字我回到原始数据核过:npm 和 GitHub 的接口、BFCL 的数据表、两个浏览器厂商的立场 issue、产品作者的原文。核不到的,文里写明是厂商自述或二手。
先拆开。“Agent 住进浏览器”可以指四件事,每件的证据差得很远:
只把执行放进标签页,模型留在云:这是唯一被验证过的,也有明确的边界。 bolt.new 是典型。它的开源仓库写明,生成的代码用 WebContainers 在浏览器里跑;它的 CTO 对 PostHog 说,别人以为他们养着一个服务器农场,其实“服务器就是你的浏览器”:多数同类产品每个会话起一个云容器,要付冷启动、网络往返和按用户计的成本,Bolt 没有这一块。规模数字都是二手的:Sacra 估算它 2024 年 10 月上线,2025 年 3 月年化收入约 4000 万美元,2025 年 5 月毛利约 40%;2025 年 3 月之后我没查到新的公开数字,所以别往后外推。毛利只有四成,说明省掉的沙箱不是成本的大头,大头应当在模型 token 上,这是我的推断,Sacra 没有拆。
成本这头,能查到的最硬的数字很旧。StackBlitz 的联合创始人 2022 年对 TechCrunch 说,每月有 200 万开发者在用,AWS 账单只有几百美元,因为计算都卸给了浏览器。那是 IDE,不是 Agent。我自己量到的是同一件事的另一面:§ 04 里同样的 3 秒空转,WebContainers 约 1.2 亿次,官方最小示例的云端实例约 160 万次。浏览器里的计算用的是你自己的 CPU,不花平台的钱。
边界是厂商自己写的。Bolt 的支持说明:桌面上 Chrome 和其他 Chromium 内核浏览器是主力,Safari 能用但有差别(代码视图只读,预览改由托管构建);后端只支持 JavaScript,Python、PHP 不兼容。WebContainers 的浏览器支持页写着 Safari 和 Firefox 还在 beta,排错页写着原生扩展默认禁用、同时开几个项目会耗尽浏览器内存。最稳的落点反而不是 Agent,是嵌进文档的交互沙箱:Angular 和 Svelte 的官方教程都说自己由 WebContainers 驱动(Angular v17 公告、SvelteKit 1.0 公告;这两处是公告里的说法,本文没有回原页核到)。
反面的证据也在这一层。CodeSandbox 的联合创始人 2025 年 11 月在 GitHub 上回复“浏览器里跑 Node 是不是死路”:他认为这仍是有效且有趣的方向,但 CodeSandbox 的收入全部来自 VM 产品,而且主要是面向 AI Agent 和文生应用的那部分,所以浏览器端的 Sandpack 最近关注得少。同一个 issue 里 2026 年 3 月有人贴出的停服通知写明 Sandpack 不再积极维护(官方原页我没找到)。他没有说浏览器路线技术上不行,说的是有人付钱的在别处。npm 上的量级也是这样:
同一个窗口(2026-09-27 到 10-26),云端沙箱 SDK 里 @vercel/sandbox 约 2176 万、e2b 约 766 万、@daytonaio/sdk 约 258 万;浏览器里的 @webcontainer/api 约 54 万、@mlc-ai/web-llm 约 45 万、@wasmer/sdk 约 2.8 万(数据来自 npm 的下载接口,其他包同一路径)。要小心读:下载量含 CI 和服务端使用,不等于终端用户,@vercel/sandbox 也可能被模板间接装进来。能读出的只是量级差了一到两个数量级,以及两边都在涨:@webcontainer/api 从 2025 年 1 月的约 11 万涨到 2026 年 9 月的约 47 万,e2b 同期从约 9.7 万涨到约 731 万。另一面,我没有查到任何产品因为“浏览器内运行不可行”而关停;Bolt 自己的做法是在 Safari 下退回托管预览,并在 2025 年加了 Bolt Cloud(托管、数据库、边缘函数)。
再把 Agent 循环也放进标签页:零后端,但没有使用量的证据。 我的两个页面是这一类:没有后端,一个链接就是一个 Agent,Key 由用户自带。最接近的公开例子是 Leaning Technologies 的 BrowserCode,在浏览器里用 BrowserPod 跑未经修改的 Claude Code 和 Codex CLI,Apache-2.0,148 个 star;它的 Show HN 得分 6,另一个把 Codex CLI 编译成 WASM 的 Show HN 得分 5。这能证明可行,证明不了有人要。我自己的两个页面也一样:没有埋点,我不知道有多少人用过。
这一类的“零成本”,更常见的做法是把账单转给终端用户,而不是把算力搬到他们的设备上。Claude 的 artifacts 让页面里的应用调用 Claude 的用量,算在使用者自己的订阅上(官方说明);Puter.js 让用户的额度付费,开发者零成本(Puter 开发者页)。成本转嫁是被验证过的机制,只是转嫁的未必是算力。
这一类还有两笔账。一笔是 § 02 说的 Key 放在页面里。另一笔是标签页的生命周期:Chrome 133 起,Energy Saver 开着,整组页面隐藏且静音超过 5 分钟,同源子组又被判为 CPU 密集时,标签页会被冻结;官方建议把后台工作搬去 Service Worker,但扩展的 Service Worker 空闲 30 秒就会被回收(那一页最后更新于 2023 年)。只等网络回包的 Agent 循环大概率不算 CPU 密集,本地推理就有风险,官方没有给判定的阈值。这是我的推断,没实测。所以它适合你在场的交互式会话,不适合放着跑半小时。
再把模型也放进来:这是最有想象力、证据最弱的一层。
覆盖面先天就窄。Chrome 的内置模型接口 Prompt API 随 Chrome 148 在 2026 年 5 月面向网页,只在桌面;Chrome 的文档写明 Android 和 iOS 不支持,要求显存大于 4GB 或 16GB 内存,磁盘剩余至少 22GB。WebKit 对它的立场是反对,Mozilla 是负面。再看用户:StatCounter 2026 年 9 月按页面浏览口径,手机约占六成。
我找到的唯一一个公开的线上数据点,是 SendCheckIt:一个给邮件标题出备选的小工具,用 Chrome 内置的 Gemini Nano,不可用时回退到托管的 Gemma。截至 2026 年 1 月,836 位用户里满足条件(Chrome 138 以上、桌面、英语)的有 340 位,占 40.7%,其中模型已就绪的约四分之一;生成一次,Gemini Nano 本地中位 7.7 秒,托管的 Gemma 约 1.3 秒。作者 2026 年 9 月把内置模型移除了,理由是为约四成用户维护两条推理路径不值得。这是单站、单一任务、英语、作者自述,但它是我能查到的最接近真实采用率的数字。
能力上,小模型“会调用”不等于“会做完”。BFCL V4 官方榜(页面标注 2026 年 4 月 12 日更新)里,Qwen3-8B 的总分 42.57%,多轮 41.75%,网页搜索 12.00%;榜首的 Claude Opus 4.5 分别是 77.47%、68.38%、84.50%。2026 年新一代的小模型(Qwen3.5、Gemma 4)不在这份榜上,它们的成绩全是厂商自报,两家对同一个 τ² 基准的 4B 级自报相差近一倍(79.9 对 42.2),没法直接比。Chrome 自己也还没有可用的原生工具调用:函数调用在 chromestatus 上仍是 “Proposed”。
成本上,被“搬到用户设备”的是一笔很小的钱。Google 的价格页上,Gemini 2.5 Flash-Lite 每百万 token 输入 0.10 美元、输出 0.40 美元。按我假设的每步 4000 输入、500 输出 token 粗算,一步约 0.0006 美元,十步的 Agent 任务约 0.6 美分(没算缓存,上下文变长会更多)。省掉的是这个量级,不是旗舰模型的价格。
真正有证据的做法是混合。Chrome 的文档把“内置模型加云端回退”写成推荐做法(Firebase AI Logic);NVIDIA 的 8B 小编排器在 τ²-bench 上靠调度更强的模型拿到高分,成绩依赖被调度的强模型,不是 8B 单独完成的(论文)。专门做浏览器操作的小模型也在进步,微软自报 Fara1.5 的 4B、9B 在 Online-Mind2Web 上是 57.3、63.4,权重 MIT 许可(论文);但这是自报,依赖截图输入,我没查到有人把它在浏览器里跑通。
两个常被拿来卖的点,成立的范围比说的窄。
安全:浏览器里的 Agent 碰不到 ~/.ssh 和环境变量,这一点是真的。本机的 CLI Agent 就被借用过:2025 年 8 月 Nx 的供应链攻击里,恶意脚本调用受害者机器上已装的 AI CLI 去枚举钱包和密钥文件,多家安全厂商都复盘过(The Hacker News、StepSecurity)。但沙箱保护的是宿主机,不是 Agent 经手的数据:Google 的 Paul Kinlan 写《浏览器就是沙箱》时自己写明,文件内容仍会发给第三方模型,模型仍可能被诱导外泄。提示注入也不归沙箱管,Chrome 的安全指引把输入输出校验、origin 限制和用户确认都留给了 Agent 和站点。“浏览器里的 Agent 和本机 CLI Agent 谁更安全”,我没有查到头对头的实证数据,只有机制上的推理。
隐私:“数据不出设备”只在本地推理时成立。本地编排加云端 API,文件内容照样发给了第三方;而本地推理恰是上面最弱的那一层。我没有查到已核实的机构把“标签页里的本地推理”当作合规方案。Cisco 的2026 隐私基准调查(5200 多名受访者)说 81% 报告生成式和智能体 AI 抬高了本地化需求,但它量化的是国家和地区层面的数据驻留,没有问端侧推理。
反过来,让页面把工具交给 Agent:还只是预览。 WebMCP 不是 Agent 住进页面,而是页面向 Agent 声明自己能做什么,来龙去脉我在另一篇里写过。截至现在:规格是 W3C 社区组的草案,不在标准轨道上;Chrome 149、Edge 150 在做 origin trial;WebKit 在 2026 年 6 月 11 日明确反对,理由里有对有副作用的操作没有同意和撤销的模型;Mozilla 在 8 月 5 日定为中立。它如果落地,页面就是服务器,用的是你已登录的会话,Agent 不必再靠截图操作页面;但今天它既不是稳定功能,本身也不让 Agent 住进标签页。
我的判断。
这一节的证据质量:规模数字几乎都来自厂商自述或聚合站,没有独立第三方;反对的论据几乎都来自卖替代品的厂商,我没查到署名清楚的非厂商专文;浏览器内推理的功耗和发热,我没找到公开实测;“满足 Gemini Nano 门槛的设备占比”也没有可靠的统计。
我自己的做法:浏览器里的 Agent 适合演示、让别人零安装试用、前端小项目和教学;真实的工作仓库,我还是在本机的 Claude Code 里跑。
没验证的:
cart.test.js 没被改动;Agent 用时 WebContainers 约 38 秒和 40 秒,Wasmer 约 27 秒和 56 秒。会让这篇结论改写的事:
showDirectoryPicker,或者 Direct Sockets 走出 Isolated Web Apps。那时文件和网络两扇门的条件会变。下一步我想做的,是把上面那批任务固定下来:每次运行时升版本就重跑一遍,比我每次手写一段“实测”可靠,那张表就是第一次的结果。还想补两件:在 Safari 里验证(要手动打开页面),和更大的云端实例。