Craft Agents 浏览器自动化实战:browser_tool 单命令驱动 Chromium 的完整指南
2026/9/16 22:49:11 网站建设 项目流程

Craft Agents 浏览器自动化实战:browser_tool 单命令驱动 Chromium 的完整指南

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

Craft Agents(Electron 桌面应用)内置了一个以单条 CLI 风格命令操控内嵌 Chromium 浏览器窗口的会话级工具browser_tool。本文基于仓库内的官方指南 browser-tools.md 编写,覆盖其全部命令、参数与实战配方,并结合 工具定义、命令运行时、Electron 主进程浏览器窗口管理器 等源码,讲清每条命令背后的实现机制,帮助你在 Agent 会话中可靠地驱动浏览器完成导航、交互、截图、剪贴板与下载等任务。

浏览器是 Source 之外的另一条路

Craft Agents 中访问外部服务的常规方式是建立 Source(API/MCP 集成),但浏览器工作流提供了更轻量的替代路径。官方指南明确给出了选择建议:

适合“浏览器优先”的场景:

  • 一次性任务,不需要可复用的集成
  • 纯 UI 工作流,且该站点的 API/MCP 覆盖差
  • Source 搭建/鉴权繁琐脆弱、而用户现在就要结果

仍应优先 Source 的场景:

  • 工作可重复执行,且需要自动化与报表
  • 需要团队级复用与稳定工具链

这个取舍的本质在于:browser_tool操作的是会话级、带真实登录 Cookie 的 Chromium 窗口,适合“此刻就要结果”的交互型任务;而可长期运行的自动化更适合走稳定的 Source 集成。

两条浏览器使用路径

指南开篇就区分了两条路径:

  1. 会话内工具面(唯一主路径)browser_tool。这是 Agent 在会话轮次中实际执行浏览器操作的入口。
  2. 辅助 CLIbun run browser-tool --help用于命令发现/模板生成,bun run browser-tool parse-url <url>用于在 Agent 轮次之外做安全的 URL 诊断。

辅助 CLI 的实现见 scripts/browser-tool.ts,它被刻意设计得“薄且确定”:只提供helplisttemplate <operation>all-templatesparse-url <url>五个子命令,并输出browser_*操作的结构化 JSON 模板(如browser_navigate: { url: 'https://example.com' })。真正的执行仍然发生在会话内的原生browser_tool工具中。

核心工作流

当不确定该操作哪个窗口时,先运行:

browser_tool({ command: "windows" })

推荐的操作顺序(指南原文的 6 步流程):

  1. open— 确保浏览器窗口存在(默认后台打开)
  2. navigate <url>— 加载 URL
  3. snapshot— 检查可访问性元素并获取引用(@e1@e2…)
  4. find <query>— 用关键词快速缩小到匹配的 ref
  5. click/fill/select— 使用 ref 进行交互
  6. screenshot --annotated(或screenshot-region)— 需要时做视觉验证

这个流程的底层依据是snapshot返回的可访问性节点结构。从 BrowserPaneFns 接口 的 TypeScript 定义可以看到,每个节点包含refrolenamevaluedescription以及focused/checked/disabled状态字段——这正是find命令做关键词匹配的搜索范围(rolenamevaluedescription)。

完整命令示例清单

以下是指南给出的browser_tool命令完整示例(33 条),全部可直接复制使用:

browser_tool({ command: "--help" }) browser_tool({ command: "open" }) browser_tool({ command: "open --foreground" }) browser_tool({ command: "navigate https://example.com" }) browser_tool({ command: "snapshot" }) browser_tool({ command: "find login button" }) browser_tool({ command: "click @e12" }) browser_tool({ command: "click-at 350 200" }) browser_tool({ command: "drag 100 200 300 400" }) browser_tool({ command: "fill @e5 user@example.com" }) browser_tool({ command: "type Hello World" }) browser_tool({ command: "select @e3 optionValue" }) browser_tool({ command: "select @e75 CNAME --assert-text Target --timeout 3000" }) browser_tool({ command: "upload @e3 /absolute/path/to/file.pdf" }) browser_tool({ command: "set-clipboard Name\tAge\nAlice\t30" }) browser_tool({ command: "get-clipboard" }) browser_tool({ command: "paste Name\tAge\nAlice\t30" }) browser_tool({ command: "scroll down 800" }) browser_tool({ command: "evaluate document.title" }) browser_tool({ command: "console 50 warn" }) browser_tool({ command: "screenshot" }) browser_tool({ command: "screenshot --annotated" }) browser_tool({ command: "screenshot-region --ref @e12 --padding 8" }) browser_tool({ command: "window-resize 1280 720" }) browser_tool({ command: "network 50 failed" }) browser_tool({ command: "wait network-idle 8000" }) browser_tool({ command: "key Enter" }) browser_tool({ command: "downloads wait 15000" }) browser_tool({ command: "focus" }) browser_tool({ command: "windows" }) browser_tool({ command: "release" }) browser_tool({ command: "hide" }) browser_tool({ command: "close" })

包装器会校验命令,并在参数缺失或非法时返回“可操作”的错误信息(见下文“常见验证错误”)。同时,大多数命令都会返回丰富的执行反馈,包括前后状态对比——滚动位置、活动元素、URL/标题变化、resize 钳制结果、请求/错误摘要、窗口归属与可见性详情。这些“执行反馈”在源码中对应 getPageMetrics:它通过注入页面的 JS 一次性采集urltitle、视口/文档尺寸、scrollX/scrollY与活动元素(tag/role/id/name),供各命令组织 before/after 摘要。

另外,从 工具定义 可以看到,浏览器类命令的输出会被自动附加一条“释放提示”:建议任务完成后调用close彻底关闭窗口,或release移除代理遮罩、把浏览器交还给用户继续浏览。

批量执行与引用:字符串模式、数组模式与转义

browser_toolcommand参数实际上接受两种输入形态,由 zod 校验 定义:z.union([z.string(), z.array(z.string())])

字符串模式支持分号批量执行,例如:

fill @e1 user@example.com; fill @e2 password123; click @e3

批量从左到右执行,并在导航类命令(navigateclickbackforward)之后自动停止,以避免 ref 静默失效。这一规则在运行时中由 NAVIGATION_COMMANDS 这个命令集合精确实现。

引用与转义规则(指南原文):

  • 双引号:fill @e5 "Hello world"
  • 单引号:wait text 'welcome back' 5000
  • 引号内的分号按字面文本处理(不是批量分隔符):
    • fill @e1 "a;b;c"; click @e2
    • screenshot-region --selector "div[data-x='a;b']" --padding 8
  • 需要时使用反斜杠转义:
    • \;表示引号外的字面分号
    • \"表示双引号文本中的字面"

从源码结构看,这套行为由 splitBatchCommands 状态机实现:逐字符扫描,跟踪inSingle/inDouble/escaped三个状态,只有当分号出现在两种引号之外时才切分批量。而\n\t\r\"\'\\的解码由 decodeEscapes 完成,未知转义序列原样保留(与指南中“\x保持\x”一致)。

数组模式(源码补充):数组输入跳过字符串解析与 token 化,逐字保留原始参数,对包含分号、Tab、换行的文本(如["evaluate", "var x = 1; var y = 2; x + y"]["paste", "Name\tAge\nAlice\t30"])更可靠——工具描述中明确建议在这类场景使用数组模式。

关键命令详解

open [--foreground|-f]

创建或复用会话浏览器窗口。默认后台打开;--foreground/-f前台聚焦。从源码看,前台打开后运行时会轮询窗口可见性直到“稳定”:超时与轮询间隔可由环境变量CRAFT_BROWSER_OPEN_SETTLE_TIMEOUT_MS(默认 1500ms)与CRAFT_BROWSER_OPEN_SETTLE_POLL_MS(默认 100ms)覆盖,见 waitForForegroundOpenVisibility。

snapshot/find <query>

snapshot返回带 ref 与元素元数据的可访问性树。find <query>对快照的可访问性节点做关键词搜索(匹配rolenamevaluedescription),返回匹配的 ref,用于在长页面中快速定位元素。

click <ref> [waitFor] [timeoutMs]/click-at <x> <y>/drag

  • click:点击snapshot中的元素 ref,可选等待模式nonenavigationnetwork-idle
  • click-at <x> <y>:按原始像素坐标点击。用于基于 Canvas 的 UI(如 Google Sheets 单元格、地图元素、图表数据点)——这些内容不产生 DOM 节点,snapshot无法给出 ref。坐标从screenshotscreenshot-region中读取。
  • drag <x1> <y1> <x2> <y2>:从 (x1, y1) 拖拽到 (x2, y2)。源码接口定义为依次执行 mousedown、插值 mousemove 事件序列、mouseup,适用于移动 Canvas 图表/对象、拖放重排、拖拽手柄调整大小、绘制或框选区域。

fill <ref> <value>/select <ref> <value> [flags]

填充文本输入或选择下拉值,都需要snapshot提供的 ref。针对现代 React/portal combobox UI,select会执行额外验证:交互成功但表单状态似乎未变化时会返回 warning。

实用标志:

  • --assert-text <text>:验证下游 UI 变化(例如字段标签变为Target
  • --assert-value <value>:验证被选中的控件确实反映了期望值
  • --timeout <ms>:验证超时,默认 2000ms

upload <ref> <path> [path2...]

把本地文件附加到<input type="file">,ref 来自snapshot。注意:

  • 必须使用绝对文件路径
  • 支持多文件:upload @e3 /path/a.pdf /path/b.jpg
  • 文件必须存在并通过安全校验(敏感路径被拦截)

从源码结构看,安全校验对应 BrowserPaneManager 引入的validateFilePathgetWorkspaceAllowedDirs(来自 server-core handlers),即在 Electron 主进程层面做路径白名单/敏感路径拦截。

type <text>

当前聚焦元素逐字符键入文本,不需要 ref。适用场景:目标是 Canvas 输入(无 DOM ref)、已通过click/click-at聚焦了元素、应用使用自定义输入机制。与fill的区别:fill聚焦某个 ref 并整体替换其值;type把按键发给当前聚焦对象。

剪贴板三件套:set-clipboard/get-clipboard/paste

  • set-clipboard <text>:程序化写入页面剪贴板,并解释常见转义序列:\t→ Tab、\n→ 换行、\r→ 回车、\\→ 字面反斜杠;未知转义原样保留。
  • get-clipboard:读取当前剪贴板文本(Tab/换行以真实字符返回)。
  • paste <text>:便捷组合命令——先写剪贴板,再触发 Ctrl+V(macOS 为 Cmd+V),等价于set-clipboard <text>之后key v meta/key v control。转义处理与set-clipboard相同,这让 TSV 式批量数据录入非常可靠。

screenshot/screenshot --annotated/screenshot-region

捕获全窗口或目标区域截图。--annotated会在可交互元素上叠加@eN标签,方便核对 ref。从 命令帮助文本 可以看到更多细节:默认输出 JPEG,加--png得到无损图;screenshot-region支持三种定位方式——坐标x y width height--ref @eN --padding <px>--selector <css-selector>

调试与同步:console/network/wait/downloads

这四个命令用于调试运行时问题、请求、同步点和下载进度:

  • console [limit] [level]:level 可选all/log/info/warn/error(见 BrowserConsoleArgs)
  • network [limit] [status]:status 可选all/failed/2xx/3xx/4xx/5xx,还可选按 method/resourceType 过滤(BrowserNetworkArgs)
  • wait <selector|text|url|network-idle> <value?> [timeoutMs]:四种等待种类,用于在易变页面上建立同步点
  • downloads [list|wait] [limit|timeoutMs]:指南特别指出,输出在可用时会包含解析后的本地savePath,让你能直接引用下载到的文件(接口定义见 BrowserDownloadsArgs 与savePath字段)

窗口管理与生命周期:focus/windows/release/hide/close

  • focus [windowId]/windows:检查与管理浏览器窗口的归属与可见性。windows的输出包含窗口 id、标题、URL、isVisible、归属类型(session/manual)、绑定会话 id 与agentControlActive(见 listWindows 接口)
  • release— 移除代理控制遮罩,窗口保持可见交给用户
  • hide— 隐藏窗口但保留会话状态
  • close— 关闭并销毁窗口

键盘与滚动

  • key <key> [modifiers]:modifiers 支持shift/control/alt/meta(BrowserKeyArgs),如key a meta(全选)、key c meta(复制)
  • scroll <up|down|left|right> [amount]:四个方向的滚动
  • evaluate <expression>:在页面上下文执行 JS 表达式,如evaluate document.title
  • window-resize <width> <height>:调整窗口尺寸(输出中会体现 resize 钳制结果)

源码架构:单工具如何驱动 Chromium 窗口

从源码结构看,整个浏览器工具体系分三层:

  1. 工具层— createBrowserTools 通过 Claude Agent SDK 的tool()注册唯一的browser_tool工具,schema 为字符串/数组联合,执行时委托给executeBrowserToolCommand。如果当前运行时没有可用的浏览器窗格回调,直接抛出Browser window controls are not available. This tool requires the desktop app.——这正是桌面应用之外(如 headless 运行时)调用浏览器命令时会遇到的错误。
  2. 命令运行时层— browser-tool-runtime.ts(约 1700 行)负责命令词法分析(批量切分、引用/转义)、参数校验、前后状态采集(getPageMetrics)、窗口归属摘要(summarizeWindows)与输出格式化(字节数、百分比、URL/标题/活动元素变化)。
  3. Electron 主进程层— BrowserPaneManager 以专用BrowserWindow拥有浏览器实例,每个实例 1:1 对应一个原生窗口,共享会话/Cookie 分区,并通过 CDP 模块 提供自动化能力(可访问性快照、元素几何等)。会话到浏览器实例的映射由回调提供方的getOrCreateForSession(sessionId)模式处理,因此各命令无需显式传实例 id。

BrowserPaneFns接口(browser-tools.ts#L123-L163)就是这两层之间的完整契约:openPanelnavigatesnapshotclickclickAtdragfilltypeselectsetClipboardgetClipboardscreenshotscreenshotRegiongetConsoleLogswindowResizegetNetworkLogswaitForsendKeygetDownloadsuploadscrollgoBackgoForwardevaluatefocusWindowreleaseControlcloseWindowhideWindowlistWindowsdetectChallenge——指南中的每条命令都能在这里找到对应回调。相关测试见 browser-tools.test.ts 与 browser-tools-remote.test.ts。

前置约束:Agent 必须先读本指南

指南“行为说明”部分要求:在首次使用浏览器工具前,Agent 必须读取本指南(~/.craft-agent/docs/browser-tools.md)。这不是文档客套——PrerequisiteManager 中有一条strict规则:工具名匹配browser_toolmcp__session__browser_tool(且不匹配外部 MCP 浏览器工具如mcp__playwright__*)时,在未读取~/.craft-agent/docs/browser-tools.md之前会拦截调用并返回“请先读取该文件再重试”的阻断消息。此外:

  • 浏览器工具默认在Explore/Safe 模式下允许使用
  • 通过操作系统控件关闭浏览器 UI 可能只是隐藏窗口;要显式拆除请用browser_tool close

辅助命令:bun run browser-tool parse-url

在 Explore 模式下做安全 URL 调试、而不需要运行通用解释器片段时,使用辅助 CLI:

bun run browser-tool parse-url https://example.com/path?q=1#hash bun run browser-tool parse-url file:///Users/me/Desktop/report.html

输出是确定性 JSON:hrefprotocolhosthostnamepathnamesearchhashorigin,对file://URL 额外附带basename。对应实现为 parseUrlDetails:基于标准URL构造器解析,file:协议时额外计算decodedPathbasename(解码 URI 组件后取路径最后一段)。非法 URL 会返回退出码 1 及错误信息。

常见验证错误

  • Missing command...→ 需要传一个命令字符串(可先试--help
  • Unknown browser_tool command ...→ 动词拼写错误/不支持,查阅 help
  • ...requires ...→ 该命令缺少必需参数
  • ...must be numbers→ 数字参数解析失败

这些错误信息的设计目标是“可操作”:指出缺什么、如何修,而不是只报失败。

实战配方:Canvas 类 UI(Google Sheets 等)

基于 Canvas 的 Web 应用(Google Sheets、Google Docs、部分地图/图表 UI)把内容渲染为<canvas>上的像素——单元格和元素不是 DOM 节点,不会出现在snapshot中。指南给出的完整工作流如下:

# 1. 导航并等待加载 navigate https://docs.google.com/spreadsheets/d/{id}/edit wait selector [aria-label="Name Box"] 10000 # 2. 通过 Name Box(DOM 元素,snapshot 能找到)定位单元格 snapshot click @nameBoxRef type A1 key Enter # 3. 编辑单元格 key F2 type Hello World key Enter # 4. 通过 TSV 剪贴板粘贴批量写入 snapshot click @nameBoxRef type A1 key Enter paste Name\tAge\tCity\nAlice\t30\tNYC\nBob\t25\tLA # 5. 通过剪贴板读取数据 key a meta # 全选(Cmd+A) key c meta # 复制(Cmd+C) get-clipboard # 返回 TSV 字符串 # 6. 按坐标点击 Canvas 单元格(坐标来自截图) click-at 350 200 # 7. 拖拽移动图表(坐标来自截图) drag 400 300 100 50 # 8. 通过导出 URL 读取数据(无需编辑) navigate https://docs.google.com/spreadsheets/d/{id}/export?format=csv&gid=0

Canvas UI 的关键原则:

  • Name Box 和公式栏是 DOM 元素——snapshot能找到它们
  • 单元格是 Canvas 像素——用click-at或键盘导航,而不是click
  • 图表和对象可移动——用drag在 Canvas 上重新定位元素
  • 键盘快捷键比点击更可靠——导航优先用key
  • 剪贴板 TSV 是最快的批量数据通道——用paste加制表符分隔值
  • 导出 URL 配合会话 Cookie 可用——只读场景不需要 API key

故障排查

“Browser window controls are not available”桌面浏览器管理器未在此运行时/会话中接线。确认你运行在 Electron 桌面应用内且会话已初始化。(源码中该错误的产生位置见 getBrowserFns。)

“Element @eX not found”ref 已过期。重新运行snapshot并使用新的 ref。这也是批量执行在导航命令后自动停止的原因——避免 ref 静默失效。

交互感觉不稳定等待页面就绪后重试,使用固定序列:opensnapshot→ 交互。必要时配合wait network-idle 8000之类的同步点,或在screenshot --annotated上核对 ref 位置。


综上,browser_tool把“浏览、查看、交互、验证、取证”压缩进一个带严格校验和丰富反馈的单命令入口:DOM 可及的元素走snapshot+ ref,Canvas 像素走click-at/drag/key,批量数据走剪贴板 TSV,状态确认走--assert-*验证与screenshot --annotated。配合 scripts/browser-tool.ts 的辅助发现能力和parse-url诊断,它覆盖了 Craft Agents 桌面端“浏览器优先”工作流所需的全部操作面。

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询