Share on

投稿日:
更新日:

ブラウザ操作の自動化と Vercel agent-browser

はじめに

PlaywrightSelenium に代表される従来のブラウザ操作ツールは、人間がテストコードを書くことを前提に設計されています。 これらのツールを使うには CSS セレクタや XPath で要素を特定し、TypeScript や Python でスクリプトを記述するプロセスが必要です。

AI エージェントにこのアプローチを取らせると、構造的な問題が生じます。 LLM はページの DOM を直接参照できないため、input[type='search'].hamburger-icon といった CSS セレクタを一般的な知識から推測して生成することになりますが、一般にサイト構造はプロジェクト毎に異なるため、推測ベースのセレクタは高い確率で失敗します。 加えて、コードを生成・実行し、エラーを解釈して修正するサイクルはトークンを浪費する課題もあります。

Vercel が公開した agent-browser はこうした課題に対して CSS セレクタの推測自体を不要にする アプローチを取っています。

agent-browser はページのアクセシビリティツリーからインタラクティブ要素を抽出し、@e1@e2 のような Refs と呼ばれる参照を割り当てます。 LLM はコードを書く代わりに、この Refs を対象とした click @e1fill @e2 "text" のようなシンプルなコマンドを実行するだけでブラウザを操作できます。

今回のブログでは、agent-browser の Refsセマンティックロケータ といった基本概念を整理した上で、内部アーキテクチャやトークン削減の仕組みを深掘りしてみたいと思います。

ブラウザ操作における 2 つのアプローチ

AI エージェントがブラウザを操作する方法は、大きく 2 つに分かれます。

コードベースのアプローチ

PlaywrightPuppeteer を使う場合、AI は以下のステップを踏みます。

  1. ページの HTML 構造を解析する
  2. 操作したい要素を特定する CSS セレクタや XPath を生成する
  3. コードを生成して実行する
  4. エラーが出れば解釈して修正する

CSS セレクタは Web サイトの更新によって無効になりやすく、生成コストも高くなります。 コード実行環境の管理や非同期処理のハンドリングも AI に委ねられるため、エラーが発生しやすいという課題があります。

コマンドベースのアプローチ

agent-browser を使う場合、AI は定義済みのコマンドを順番に実行するだけです。

CSS セレクタを生成する必要はなく、スナップショットで得た セマンティックロケータ(@e1, @e2 のような Refs 参照)を指定する だけで要素を操作できます。 セマンティックロケータは、DOM の構造ではなくアクセシビリティツリー上の要素に紐付けられた参照であり、ページの CSS クラス名やタグ構造に依存しません。

また、各コマンドはステートレスで独立しており、ブラウザインスタンスへの参照を保持する必要もありません。

観点コードベースコマンドベース
要素の特定方法CSS セレクタ / XPath を生成スナップショットの Refs を指定
エラー処理AI がコードを修正して再実行コマンドを再実行するだけ
状態管理ブラウザオブジェクトへの参照が必要ステートレス
トークン消費コード生成・修正で消費が多いコマンドと Refs だけで完結

以降のセクションでは、agent-browser がこのコマンドベースの設計をどのようなアーキテクチャで実現しているのか、Refs 参照・セッション分離・JSON 出力の仕組みを順に見ていきます。

Playwright MCP とは何か

agent-browser を理解する前提として、Playwright MCP の概要を整理します。

Playwright MCP は Microsoft が公開した MCP を通じて LLM がブラウザを操作できるようにするツールです。 LLM は listTools() で利用可能なブラウザ操作ツールを取得し、callTool() でツールを呼び出すことでブラウザを制御します。

Playwright MCP の主な特徴は以下の通りです。

  • MCP プロトコル(HTTP / SSE または stdio)でエージェントと通信する
  • ページの状態をアクセシビリティスナップショット(アクセシビリティツリー全体)として返す
  • Node.js で実装されており npm パッケージとして配布されている

Playwright MCP のトークン消費問題

Playwright MCP の課題は、browser_snapshot ツールの返却値にあります。 ページ全体のアクセシビリティツリーをテキストで返却するため、1 回のスナップショットで数千〜数万トークンを消費することがあります。

Agent Loop では各イテレーションで LLM がページ状態を確認するためにスナップショットを取得します。 イテレーション数が増えるほど Context Window の消費が加速し、長いタスクでは LLM の入力コンテキストの大部分をスナップショットデータが占めることになります。

Agent Loop や Context Window の概念については こちらのブログ でまとめています。

agent-browser のアーキテクチャ

agent-browser は Vercel が開発したブラウザ自動化のための OSS(Apache-2.0 ライセンス)です。 GitHub では 28,000 を超えるスターを獲得しており、AI エージェント開発者の間で注目を集めています。

※ 名前に「browser」と付いていますが、ブラウザそのものではなく実体は CLI です。

Browser automation CLI for AI agents. Fast native Rust CLI.

AI にとって扱いやすいコマンド体系と、複雑な DOM 操作を不要にする Refs システムが大きな特徴です。 agent-browser は Rust で実装されたネイティブバイナリとして動作し、Unix ソケット経由で Daemon プロセスと通信します。

構成要素

agent-browser は 3 つの主要コンポーネントで構成されています。

agent-browser-architecture.png

サポートしているブラウザエンジンは以下の通りです。

エンジン通信方式概要
Chrome(デフォルト)CDPChrome for Testing、Chromium、Brave 等の CDP 対応ブラウザを自動検出・起動する
LightpandaCDPZig 製の軽量ヘッドレスブラウザ。Chrome と同じ CDP パスで動作する
Mobile SafariAppium + XCUITestiOS Simulator 上の Safari。CDP ではなく WebDriver 経由で通信する

--engine フラグで Chrome と Lightpanda を切り替えることができ、iOS Simulator は --device フラグで指定します。

以下は、AI エージェントが agent-browser を通じてブラウザを操作する際の処理フローです。

agent-browser-processing-flow.png

CLI(Rust バイナリ)

エージェントや AI コーディングアシスタントが直接呼び出すコマンドラインツールです。 ホストマシン上でフォアグラウンドプロセスとして実行され、コマンドの発行と結果の受け取りを担います。 agent-browser openagent-browser snapshotagent-browser click @e1 のようにコマンドベースで Daemon に指示を出します。

Daemon(バックグラウンドプロセス)

CLI と同じホストマシン上でバックグラウンドプロセスとして動作し、CLI から受け取ったコマンドを解釈して CDP(Chrome DevTools Protocol) 経由で Chrome を制御します。 CLI からの最初の呼び出し時に自動起動してセッション中は Daemon プロセスとして常駐し、ソケットファイルは ~/.agent-browser/sessions/<session>/daemon.sock に配置されます。

Chrome for Testing

agent-browser が操作するブラウザプロセスです。 ローカル実行の場合はホストマシン上で、クラウドプロバイダ利用時はリモートサーバ上で動作します。 インストール時に agent-browser install を実行することで Chrome for Testing からダウンロードされます。 Playwright が同梱する Chromium とは独立した管理になるため、既存の Playwright 環境と干渉しません。

AI ネイティブ設計の 3 つの特徴

agent-browser の設計には、AI エージェントとの連携を前提にした 3 つの特徴があります。

1. ステートレスなコマンド設計

各コマンドは独立して実行できます。 Playwright では browser.newPage() で取得した page オブジェクトを保持し、page.click() のようなオブジェクト指向 API でメソッドを呼び出す必要がありますが、agent-browser では click @e1 のようにコマンドを発行するだけで済みます。 これにより、LLM がオブジェクトの参照や非同期処理の状態を追跡する必要がなくなるため、Context Window の負担を軽減できます。

2. 機械可読な JSON 出力

--json オプションを付けると、全てのコマンドの実行結果が JSON 形式で返却されます。 成否を示す success フラグや、スナップショット・取得テキスト等のデータが構造化されているため、LLM は結果をそのまま次のアクション判断に利用できます。

3. セマンティックロケータによる間接参照

snapshot -i で取得した Refs(@e1, @e2 等)は セマンティックロケータ と呼ばれ、セッション内で再利用できます。 LLM は CSS セレクタを推測する代わりに、ページのアクセシビリティツリーから割り当てられた Refs を使って操作対象を指定します。 毎回ページ全体を再取得する必要がないため、Agent Loop でのトークン消費を抑えることができます。

本サイト(ren510.dev)の場合

セッション管理

agent-browser はセッション単位でブラウザインスタンスを管理します。 --session フラグでセッションを指定することで、複数のセッションが独立したブラウザインスタンスを持つことができます。

各セッションの Daemon プロセスは独立したソケットファイルを持ち、user-data-dir も分離されます。 このため、Playwright MCP の SingletonLock 問題(後述)が根本的に発生しない構造になっています。

Refs 参照によるトークン削減

agent-browser の設計において最も重要な概念が セマンティックロケータ による Refs 参照です。 Playwright MCP がページ全体のアクセシビリティツリー(1 ページあたり 3,000 - 5,000 トークン程度)を毎回返却するのに対し、agent-browser の snapshot -i はインタラクティブ要素のみを Refs 付きで返却するため、1 ページあたり 200 - 400 トークン程度に収まります。

インタラクティブ要素のみを抽出

snapshot -i はクリック・入力・選択が可能なインタラクティブ要素のみを返します。 多くのページではコンテンツ要素(段落テキスト・見出し・リスト等)が全体の大部分を占めますが、AI エージェントが操作するために必要なのは基本的にインタラクティブ要素のみ です。

agent-browser の実装 を確認してみると、CLI の INTERACTIVE_ROLES では特定のロール(18 種類)がインタラクティブ要素として定義されていることが分かります。

snapshot -i はこれらのロールに該当する要素のみを抽出して返却します。

DOM 全体を渡す従来のアプローチでは、以下のような HTML がそのまま LLM に渡されていました。

LLM はこの HTML を解析して CSS セレクタを推測する必要がありますが、通常 クラス名やタグ構造はプロジェクト毎に異なるため、推測が外れて操作に失敗する ケースが多くなります。

agent-browser のセマンティックスナップショットでは、同じページが以下のコンパクトな形式で表現されます。

従来の Playwright ベースのアプローチでは、LLM は以下のようなコードを推測生成する必要がありました。

ここで input[type="email"]button.login-btn は LLM が HTML 構造から推測したセレクタであり、実際の DOM と一致する保証はありません。

agent-browser では、LLM はスナップショットで得た Refs を指定するだけで同じ操作を実行できます。

Refs はスナップショット上の要素と 1 対 1 で対応しているため、セレクタを推測する必要がありません。

トークン消費の比較

Playwright MCP と agent-browser のトークン消費の違いを比較してみます。

方式1 ページあたりの消費量3 ページ遷移時の累積
Playwright MCP3,000 - 5,000 トークン9,000 - 15,000 トークン
agent-browser(Refs)200 - 400 トークン600 - 1,200 トークン

こちらの記事 では Playwright MCP と比較して Context Window の消費量が約 93% 削減(推定値) されることが言及されています。

agent-browser では一度取得した Refs をセッション内で再利用できるため、操作の度にスナップショット全体を再取得する必要はありません。 ページ構成が変化しない限り、Refs を指定してコマンドを発行するだけで済むため、イテレーションを重ねてもトークン消費の増加が緩やかになります。

削減率はページの複雑さに依存しますが、要素数が多くコンテンツテキストが豊富なページほど削減効果が大きく なる特徴があります。

diff モードによる差分取得

agent-browser はスナップショットの差分取得(snapshot --diff)にも対応しています。 操作後に変化した部分のみを取得することで、どの要素が追加・変更されたかをより少ないトークンで把握することができます。

フォーム送信後のエラーメッセージの確認やページ遷移後に変化した要素の把握といった、変化した箇所だけを知りたい場面で有効です。

annotated スナップショットの活用

--annotate フラグを使うと、インタラクティブ要素に番号ラベルを重ねたスクリーンショットを取得できます。

テキストだけでは判別しにくい複雑なレイアウトや、同じ名前のボタンが複数存在する場合でも、視覚情報と Refs を組み合わせることで正確な要素の特定ができます。

Playwright MCP との設計比較

agent-browser と Playwright MCP は、どちらも AI エージェントのブラウザ操作を支援するツールですが、設計思想と接続方式に大きな違いがあります。

通信プロトコルの違い

  • Playwright MCP(@playwright/mcp)
  • agent-browser
項目@playwright/mcpagent-browser
プロトコルMCP over SSE / stdioCLI + Unix Socket
実装言語Node.jsRust(CLI + Daemon)
セッション管理固定 user-data-dir で 1 ブラウザ--session フラグでセッション別に分離
並行セッション不可(SingletonLock)可能(セッション毎に独立)
ページ状態の取得アクセシビリティツリー全体セマンティックロケータ付きスナップショット
LLM の操作方式CSS セレクタベース@e Refs 参照(セレクタ推測不要)
トークン効率3,000 - 5,000 tokens / ページ200 - 400 tokens / ページ(約 93% 削減)
MCP 対応対応非対応(CLI 直接呼び出し)
コマンド参照プロンプトにハードコード--help 出力からの動的注入が可能
メモリ消費(Daemon)約 140MB(Node.js + V8)約 7MB(Rust バイナリ)

SingletonLock 問題

Playwright MCP で複数の並行テストが同一の user-data-dir を共有する構成では、Chrome の SingletonLock 問題が発生します。

Chromium の ProcessSingleton は、同一の user-data-dir に対して複数のブラウザプロセスが同時に起動することを防ぐ排他制御の仕組みです。

同じディレクトリを指定した 2 つ目のプロセスは、既存プロセスにプロセス間通信(IPC:Inter-Process Communication)でシグナルを送り即座に終了するため、Playwright はこれを CDP 接続前にプロセスが消えたと判定してエラー を返します。

agent-browser はセッション毎に独立した Daemon プロセスと user-data-dir を持つため、この問題が 構造的に発生しません。

MCP 非対応という制約

agent-browser の注意点として、MCP プロトコルに対応していないことが挙げられます。 LLM エージェントが MCP クライアントとして動作する実装(MCPBridgeClient 等)では、そのまま agent-browser を差し込むことができません。

agent-browser は CLI として直接呼び出す設計を取っています。 Claude や Codex のようなコーディングアシスタントから直接呼び出す場合は、agent-browser --help の出力をスキルとして与えることで LLM にコマンド体系を学習させ、CLI を直接実行させるアプローチが想定されています。 この --help 出力を起動時に動的に取得して LLM のプロンプトに注入する方法を取ると、agent-browser がアップデートされて新しいコマンドが追加された場合にも自動で対応できるため、プロンプトのハードコードによるメンテナンス負荷を低減できます。

既存の MCP ベースのエージェント実装から移行する場合は、エージェントの実行層を CLI コマンド呼び出しに変更する必要があります。

batch コマンドによるレイテンシ削減

CLI ベースの設計ではコマンドを 1 つずつ実行する度に往復のオーバヘッドが発生しますが、batch コマンドを使うことで複数のコマンドを 1 回の呼び出しにまとめることができます。

バッチ実行を使うことで、LLM が生成した一連の操作コマンドをまとめて送信でき、コマンド毎の往復レイテンシを削減できます。

主要コマンドと AI エージェントのワークフロー

基本ワークフロー

AI エージェントが agent-browser を使う際の基本パターンは以下の通りです。

このワークフローにおいて、LLM は snapshot -i の出力(Refs リスト)と各コマンドの実行結果のみをコンテキストに保持すればよく、ページ全体の DOM やアクセシビリティツリーを保持する必要がありません。

セッションの並列実行

複数の独立したセッションを並列に実行する場合、--session フラグでセッションを分離します。

各セッションは独立した Daemon と Chrome インスタンスを持つため、互いに干渉しません。

クラウドブラウザプロバイダとの統合

agent-browser はローカル Chrome だけでなく、複数のクラウドブラウザプロバイダと統合できます。

プロバイダ用途
Browserlessクラウドブラウザインフラ(セルフホスト対応)
Browserbaseリモートブラウザインフラ(エージェント向け)
Browser Use CloudAI エージェント向けクラウドブラウザ
AWS Bedrock AgentCoreAWS 統合のクラウドブラウザセッション
iOS Simulatorモバイル Safari のテスト(macOS + Xcode 必須)

プロバイダの切り替えは -p フラグか環境変数で行います。 コマンド体系は変わりません。

ローカル実行時と同じコマンドが使えるため、例えば、ローカルで開発して CI/CD はクラウドブラウザで実行するといったワークフローをシームレスに実現することができます。

Rust ネイティブ実装の性能特性

agent-browser の CLI と Daemon は Rust で実装されています。

初期バージョンでは CLI が Rust、Daemon が Node.js + Playwright という構成でしたが、v0.20.0 以降では Daemon プロセスも Rust ネイティブに移行され、Playwright を経由せず CDP で直接ブラウザと通信する構成に変わっています。

指標Node.js Daemon(旧)Rust ネイティブ Daemon(現行)
Daemon RSS約 140MB約 7MB
コールドスタートNode.js 起動時間あり単一バイナリで高速
配布サイズnpm + Playwright Chromium 含むバイナリ + Chrome for Testing のみ

コマンドレイテンシ(navigatesnapshotclick 等)の大部分は Chrome の CDP 処理時間に依存するため、Daemon の実装言語による差は小さいと報告されています。 Rust 実装の主なメリットはメモリ消費とコールドスタート速度にあります。

Command latency is dominated by Chrome (CDP round-trips), not the daemon. Both daemons are thin relays between the CLI and Chrome, so per-command speedups are typically small.

特に長時間動作する CI 環境やメモリが制約されたコンテナ環境では、Daemon が 7MB で動作することの恩恵が大きくなります。

CI 環境でテストケース毎に新しいセッションを立ち上げる場合、コールドスタートのコストがテスト全体の実行時間に蓄積されます。 特に多数の短いテストケースを逐次実行するシナリオでは、コールドスタート速度がスループットに直結します。

Observability ダッシュボード

agent-browser には v0.25.1 以降で Observability ダッシュボードが組み込まれています。

agent-browser stream enable でリアルタイムの WebSocket ストリーミングを有効化し、ブラウザ上でセッションの状態・コマンド履歴・LLM との対話を確認することができます。

ダッシュボードには AI チャット機能も統合されており、自然言語でブラウザ操作を指示することもできます。

AI チャットによるブラウザ操作

agent-browser の chat コマンドを使うと、自然言語の指示から agent-browser のコマンドを自動生成・実行できます。 この機能は Vercel AI Gateway を経由して LLM を呼び出すため、事前に API キーの設定が必要です。

ai-chat-1.png

AI Gateway の利用にはクレジットが必要ですが、登録時に $5.00 分のディスカウントが付与されるため、試用の範囲であれば無料で利用できます。

ai-chat-2.png

以下は、実際に chat コマンドで本サイト(ren510.dev)のブログページに遷移した例です。

「open ren510.dev and click the Blog link」という自然言語の指示から、LLM が opensnapshot -iclick @e13screenshot の 4 コマンドを自動生成し、順番に実行しています。 snapshot -i で取得した Refs から Blog リンクに該当する @e13 を特定し、クリックしていることが分かります。

実際に snapshot -i を実行してみると、以下の通り、Blog へのリンクが @e13 として Refs 付きで返却されていることが確認できます。

CLI での chat コマンドに加え、ダッシュボード(デフォルト http://localhost:4848)の Chat タブからも同じ操作が可能です。

  • 初期画面
ai-chat-3.png
  • Chat から指示を出した後
ai-chat-4.png

おわりに

AI エージェントによるブラウザ操作では、CSS セレクタの推測生成やトークンの浪費が構造的な課題となっていました。 agent-browser は、アクセシビリティツリーから Refs を割り当てることでセレクタの推測を排除し、snapshot -i によるインタラクティブ要素の絞り込みでトークン消費を削減しています。

agent-browser が採用しているアクセシビリティツリーベースの要素参照やトークン削減の概念自体は、Building Browser AgentsWebGames ベンチマーク といった論文で研究されている手法に基づいています。 agent-browser はこれらの知見を CLI ツールとして実装したプロジェクトで、今年 1 月にリポジトリが公開されたばかりです。 2026 年 4 月時点では GA しておらず情報量が少ないのが実情です。

本ブログでは Playwright MCP との比較についても触れましたが、両者は設計思想が異なります。 Playwright MCP はブラウザ操作を MCP プロトコルで標準化することに主眼を置いており、agent-browser は AI エージェント向けのトークン効率とセレクタ推測の排除に焦点を当てています。 自身のエージェントがどのような実行方式を取っているかに応じて、適した方を選択してみてください。

参考・引用