Agent 可使用 Browser Run 通过 Chrome DevTools Protocol (CDP) 检查并与网页交互。Beta 当 Agent 需要理解渲染页面、截取屏幕截图、调试前端行为或提取仅在 JavaScript 运行后才可用的信息时,浏览器工具很有用。
与固定浏览器操作集(点击、截图、导航)不同,模型编写代码,通过 cdp connector 对实时浏览器会话运行 CDP 命令——访问协议中的所有 domain、command、event 和 type。execution 使用持久化 Code Mode 运行时,因此运行可在审批时暂停,并在浏览器会话保持完整的情况下恢复。
在以下场景使用浏览器工具:
- 打开并检查实时网页。
- 截取屏幕截图或页面状态。
- 抓取静态 HTML 中不存在的渲染内容。
- 使用 CDP 命令调试前端问题。
- 将页面检查与其他工具(如 RAG 或 Sandbox)结合。
Browser Run 提供 Agent 可通过 CDP 控制的隔离浏览器会话。Agent 可导航页面、评估 JavaScript、读取 DOM 状态、截取屏幕截图,并检查网络或控制台输出。
由于浏览器会话在 Worker isolate 外运行,请将其用于需要真实浏览器环境的工作,而非轻量 HTTP fetch。
使用 Browser Run 和 Worker Loader binding 创建浏览器工具,然后将这些工具传入模型调用。
import { AIChatAgent } from "@cloudflare/ai-chat";
import { createBrowserTools } from "agents/browser/ai";
import { streamText, convertToModelMessages, stepCountIs } from "ai";
import { createWorkersAI } from "workers-ai-provider";
export class BrowserAgent extends AIChatAgent {
async onChatMessage() {
const workersai = createWorkersAI({ binding: this.env.AI });
const browserTools = createBrowserTools({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
});
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You can inspect web pages with browser tools.",
messages: await convertToModelMessages(this.messages),
tools: browserTools,
stopWhen: stepCountIs(10),
});
return result.toUIMessageStreamResponse();
}
}import { AIChatAgent } from "@cloudflare/ai-chat";
import { createBrowserTools } from "agents/browser/ai";
import { streamText, convertToModelMessages, stepCountIs } from "ai";
import { createWorkersAI } from "workers-ai-provider";
export class BrowserAgent extends AIChatAgent<Env> {
async onChatMessage() {
const workersai = createWorkersAI({ binding: this.env.AI });
const browserTools = createBrowserTools({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
});
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You can inspect web pages with browser tools.",
messages: await convertToModelMessages(this.messages),
tools: browserTools,
stopWhen: stepCountIs(10),
});
return result.toUIMessageStreamResponse();
}
}浏览器工具必须在 Durable Object(如 Agent)内创建——持久化运行时 facet 和会话存储位于其 ctx 上。helper 暴露一个持久化 CDP tool,以及存在 browser binding 时的无状态 Quick Action tool:
| 工具 | 描述 |
|---|---|
browser_execute |
通过 CDP 对实时浏览器运行沙箱化代码——截图、DOM 读取、JavaScript 评估等。 |
browser_markdown |
将页面或原始 HTML 读取为 Markdown。 |
browser_extract |
使用 AI 从页面提取结构化数据。 |
browser_links |
列出页面上的链接。 |
browser_scrape |
按 CSS 选择器抓取特定元素。 |
要发现协议 surface,模型调用 cdp.spec()(实时、规范化的 CDP 协议描述)或运行时的内置 codemode.search() 和 codemode.describe()。
将 Browser Run 和 Worker Loader 绑定添加到 wrangler.jsonc。
{
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "BROWSER"
},
"worker_loaders": [
{
"binding": "LOADER"
}
]
}compatibility_flags = [ "nodejs_compat" ]
[browser]
binding = "BROWSER"
[[worker_loaders]]
binding = "LOADER"tool 背后的持久化运行时位于 Durable Object facet 中,因此 Worker 入口必须导出它(@cloudflare/codemode/vite 插件会自动完成):
export { CodemodeRuntime } from "agents/browser";export { CodemodeRuntime } from "agents/browser";agents/browser 为浏览器 tool 设置重新导出 Code Mode 运行时。Code Mode 特定示例也可从 @cloudflare/codemode 导入 CodemodeRuntime。
默认每次 execution 获得新的浏览器会话,运行结束时销毁(one-shot)。传入 session 选项可使用另外两种模式:
createBrowserTools({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
session: { mode: "dynamic" }, // or { mode: "reuse", key: "main" }
});createBrowserTools({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
session: { mode: "dynamic" }, // or { mode: "reuse", key: "main" }
});one-shot(默认)— 每次 execution 新会话;execution 达到终端状态时确定性清理。reuse— 命名共享会话,在显式关闭或 sweep 前跨 execution 持久化。dynamic— 以 one-shot 开始;模型可用cdp.startSession()提升会话(例如登录页面后),使后续 execution 在同一浏览器中继续。
在 reuse 和 dynamic 模式下,沙箱额外获得 cdp.startSession()、cdp.sessionInfo()、cdp.closeSession() 和 cdp.resetSession()。
会话在 Durable Object 存储中持久跟踪,因此可在休眠和审批暂停中存活——暂停等待人工审批的运行会与其浏览器会话、标签页和 cookie 一起恢复。若 Browser Run 在暂停等待期间使会话过期,恢复会抛出清晰错误,模型重新开始。
对于宿主侧接线(会话检查、清理、回收陈旧暂停),使用 createBrowserRuntime,返回 { runtime, connector, tools }。从调度任务调用 connector.sweep() 回收过期或陈旧会话,调用 runtime.expirePaused() 拒绝从未批准的陈旧暂停。
对交互式多步自动化使用 browser_execute。对一次性浏览任务,使用 Browser Run 快捷操作。快捷操作只需 browser 绑定,无需 Worker Loader 或沙箱。
import { createQuickActionTools } from "agents/browser/ai";
const tools = createQuickActionTools({ browser: this.env.BROWSER });
// browser_markdown, browser_extract, browser_links, browser_scrapeimport { createQuickActionTools } from "agents/browser/ai";
const tools = createQuickActionTools({ browser: this.env.BROWSER });
// browser_markdown, browser_extract, browser_links, browser_scrape默认情况下,存在 browser binding 时 createBrowserTools 和 createBrowserRuntime 包含 Quick Action tool。传入 quickActions: false 仅保留 browser_execute,或传入 quickActions: { actions, maxChars, options } 配置无状态 tool。
createBrowserTools({
browser: this.env.BROWSER,
loader: this.env.LOADER,
quickActions: { maxChars: 20_000 },
});createBrowserTools({
browser: this.env.BROWSER,
loader: this.env.LOADER,
quickActions: { maxChars: 20_000 },
});每个 Quick Action 结果限制为 maxChars,在保护模型上下文窗口的同时保留结果形状。宿主提供的请求选项(如 cookies、authenticate、gotoOptions 和 viewport)通过 options 一次性传入,不暴露给模型。
Quick Action 需要 Worker compatibility_date 为 2026-03-24 或更高,且本地 wrangler dev 时 browser binding 需 remote: true。
Live View 让人类实时观看或控制运行中的浏览器会话。用于 human-in-the-loop 步骤,如登录、MFA、CAPTCHA 或敏感输入。
由于 Code Mode 运行时可在浏览器会话完整的情况下暂停运行,交接遵循以下模式:
- 模型调用
cdp.getLiveViewUrl()获取当前标签页的链接。 - Agent 向用户展示链接。
- 模型进行需审批的调用,运行持久化暂停。
- 审批后,运行在同一会话中恢复。
async () => {
const { targetId } = await cdp.send({
method: "Target.createTarget",
params: { url: "https://example.com/login" },
});
const { url } = await cdp.getLiveViewUrl({ targetId, mode: "tab" });
return { needsHumanLogin: url };
};async () => {
const { targetId } = await cdp.send({
method: "Target.createTarget",
params: { url: "https://example.com/login" },
});
const { url } = await cdp.getLiveViewUrl({ targetId, mode: "tab" });
return { needsHumanLogin: url };
};mode: "tab" 为交互式页面视图,mode: "devtools" 为完整 DevTools 检查器。URL 有效期约五分钟。再次调用 cdp.getLiveViewUrl() 创建新 URL。
从宿主侧,connector.liveView() 返回共享会话标签页的 Live View URL。每个标签页包含当前 pageUrl,Agent UI 可标注标签页并跳过空白或内部页面。
会话录制 将 Browser Run 会话捕获为结构化 rrweb 事件。会话关闭后,用录制审计或调试自主浏览器运行的行为。
按会话通过 recording: true 选择加入:
import { createBrowserRuntime } from "agents/browser/ai";
const { connector } = createBrowserRuntime({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
session: { mode: "reuse", key: "main", recording: true },
});import { createBrowserRuntime } from "agents/browser/ai";
const { connector } = createBrowserRuntime({
ctx: this.ctx,
browser: this.env.BROWSER,
loader: this.env.LOADER,
session: { mode: "reuse", key: "main", recording: true },
});会话关闭后 finalize 录制。在会话存活时捕获 session ID,然后从 Browser Rendering REST API 获取录制:
import { getBrowserRecording } from "agents/browser";
const { sessionId } = (await connector.sessionInfo()) ?? {};
if (!sessionId) {
throw new Error("No active browser session");
}
const recording = await getBrowserRecording({
accountId: this.env.CF_ACCOUNT_ID,
apiToken: this.env.CF_API_TOKEN,
sessionId,
});import { getBrowserRecording } from "agents/browser";
const { sessionId } = (await connector.sessionInfo()) ?? {};
if (!sessionId) {
throw new Error("No active browser session");
}
const recording = await getBrowserRecording({
accountId: this.env.CF_ACCOUNT_ID,
apiToken: this.env.CF_API_TOKEN,
sessionId,
});录制保留 30 天,每会话上限两小时。在共享 reuse 和 dynamic 会话上谨慎使用录制,因为录制跨越完整会话生命周期。
在 browser_execute 内,cdp 命名空间提供以下方法。所有方法接受单个对象参数:
| 方法 | 描述 |
|---|---|
cdp.send({ method, params?, sessionId?, timeoutMs? }) |
发送 CDP 命令并等待响应。 |
cdp.attachToTarget({ targetId, timeoutMs? }) |
附加到 target;返回页面范围 send 调用的 { sessionId }。 |
cdp.spec() |
可搜索、规范化的 CDP 协议 spec。 |
cdp.getDebugLog({ limit? }) |
此 execution 连接最近的 CDP 流量(发送、接收、警告)。 |
cdp.clearDebugLog() |
清除 debug log 缓冲区。 |
cdp.getLiveViewUrl({ targetId?, mode? }) |
为标签页创建 Live View URL。 |
cdp.startSession() (reuse/dynamic) |
提升或确保共享会话;返回其信息。 |
cdp.sessionInfo() (reuse/dynamic) |
共享会话信息,或 null。 |
cdp.closeSession() (reuse/dynamic) |
关闭共享会话。 |
cdp.resetSession() (reuse/dynamic) |
关闭并替换共享会话。 |
每个 cdp.* 调用记录在运行时的持久化 log 中。若运行暂停(审批)或沙箱 abort,恢复会重放 log 并继续——因此 connector 调用必须顺序且确定性。模型代码不得 Promise.all CDP 调用(tool 说明会强制执行),返回的 sessionId 是稳定的会话 handle,在暂停/恢复重连中保持有效。
完整演练(包括 Browser Run 设置、tool 定义和截图捕获)请参阅浏览器 Agent 示例。