跳转到内容

浏览器自动化

Beta

octo 通过 DevTools Protocol(CDP)直接操作一个真实的 Chrome 标签页——不依赖任何 headless 浏览器 框架,也不需要额外的运行时。

Terminal window
octo browser setup

browser 工具按下面这个顺序尝试拿到一个页面:

  1. 已知的调试端口(config.yml 里的 browser.connect_port)——直接连,失败了不会退而求其次。 这就是 octo browser setup 帮你接好的那条路。
  2. 接入一个已经在跑、开了远程调试的 Chromebrowser.attach_running: true)——复用你的登录态; 绝不会去劫持一个原本没开调试的浏览器。
  3. 启动一个全新的临时 profile——上面两个都没配或者都不可用时的默认选项。

不管走哪条路连上,octo 都会打开一个全新标签页,而不是复用你已经开着的某个标签页(包括它自己 Web UI 的那个)——要操作一个已有标签页,必须显式调用 pages/select_page 这类动作。连接会在整个 会话里复用,调试器授权提示只需要点一次,不会每次导航都弹。

Terminal window
octo browser setup

带你一步步打开 chrome://inspect/#remote-debugging(Chrome 144+ 之后默认 profile 上的旧 --remote-debugging-port flag 被禁用了,所以走 inspect 页面的勾选框是目前支持的路径),然后循环 探测 9222 端口——不只是确认连上了,还会验证一次真正的页面级 CDP 调用能成功(浏览器级连接可能成功, 但页面控制在新版 Chrome 上还是会失败)。成功之后会把 browser.connect_port 存进你的配置;失败就 提示你去开那个开关,回车重试,或者随时退出、以后再跑一遍。

这个动作没有对应的 CLI 命令——录制是通过 browser 工具的 record_start / record_stop 两个动作 驱动的,可以由模型调用,也可以点 Web UI 的录制按钮。

关键的一点:它录的是你做的操作,不是模型做的操作。 调用 record_start 之后,agent 会把浏览器 交给你,由你亲自完成这些步骤,说一声“做完了”之后,agent 才调用 record_stop <name>

每一步会记录:动作类型(click / type / select / upload / navigate)、一个锚定在最近的、 带稳定 id 的祖先元素上的选择器(而不是脆弱的、按位置算的选择器链)、这个元素的可见文本,以及 当时的 URL。之后会有一个模型处理步骤对原始录制做提炼——去掉绕路的死胡同、把你输入的具体值换成 {{param}} 占位符、写一段描述——但它只能重新排列或者重命名真实录到的步骤,不能凭空造一个新目标: 任何一步如果它的选择器不在原始录制里,就会被拒绝,退回用原始版本。

录制会以纯 YAML 的形式存在 ~/.octo/browser-skills/<name>.yaml——可读、可手改、可以用 git 追踪 差异。

browser(action: "run_skill", name: "<录制名>", params: { ... })

回放在常见情况下是确定性的——不涉及模型调用。每一步会先等目标出现,再执行,如果录制里声明了 verify 还会做一次校验。几个值得知道的健壮性细节:

  • 点击会先找原始录制里的那个选择器;如果页面结构有点变化,但一个带着录制时记下的那段文字的元素 还在,就会点那个元素,而不是直接失败。
  • 如果某一步打开了新标签页,后续步骤会自动跟到那个新标签页上。
  • 输入之后如果字段意外变成空的,会先清空重打一次,再失败才真正判定这一步失败。

返回结果是一个结构化对象——{skill, steps, outputs, self_healed?}——所以一段录制声明的 outputs(提取出来的值、下载文件的路径)可以通过 skill("browser:<name>", params) 直接接进 工作流

如果某一步的选择器找不到任何东西了——而且只有在配置了用于这个用途的模型时——octo 会对页面当前 可交互的元素取一份文本摘要(选择器 + 可见文本,不截图,不挑模型),把这份摘要连同预期动作、 预期的文字标签、失效的旧选择器一起发给模型,让它只回复一个修正后的 CSS 选择器。修正会被重试一次, 如果成功就写回这段录制的 YAML 文件——所以一次自愈是持久生效的,不是临时补丁,以后每次回放都不用 再修一遍。

浏览器动作走的是和其他工具一样的权限引擎——在一个已登录账号上点击或者提交表单,会被当成一次 真实的、影响很大的动作,而不是只读的一步。截图只有在当前模型支持视觉能力时才会以图片 block 返回;纯文本模型拿到的是一条文字提示,而不是一个会被拒绝的图片 block。

下一步:录制可以通过 skill("browser:<name>") 直接接进工作流脚本。