Jevで動くブラウザエージェントとClaude Code + Playwright MCPに同じ操作を任せて比べてみた

Jevで動くブラウザエージェントとClaude Code + Playwright MCPに同じ操作を任せて比べてみた

判断と確率だけを返すモデルJevでブラウザを操作するOSS、jev-ultrafastとlaya-ultrafastをClaude Code + Playwright MCPと14シナリオで比べました。英語の検索や並べ替えは数秒で終わる一方、パスワード欄の除外、入力後のEnterなし、日本語の渡し方で止まりました。
2026.09.28

こんにちは。サービス開発部の武田です。

2026年9月15日にTypeSafe AIが、テキストを生成せず判断と確率だけを返すモデル「Jev」を公開しました。直後から、Jevにブラウザの操作を判断させるOSSがいくつも出ています。Browser Useの「jev-ultrafast」は、Google Flightsの検索を7.1秒で終えたと公表しています。それを元にした「laya-ultrafast」も出ました。判断役をJevのままにもできますし、オープンウェイトの判断モデル「Laya」に替えてMacだけで動かすこともできます。

https://github.com/browser-use/jev-ultrafast

https://github.com/ipenywis/laya-ultrafast

普段のブラウザ操作は、Claude CodeにPlaywright MCPを使わせる形で実行しています。同じ操作をこれらのツールに任せたら何が違うのかが気になったので、今回はフォームとショップ、公開デモサイト、Wikipediaでシナリオを用意し、4つの構成に同じゴール(プロンプト)を渡して比べました。

結果は実行時時点のもので、アップデートによって改善されるものもあるので注意してください。

先に結論

  • Claude Code + Playwright MCPは、今回の14シナリオを計40回動かして全部成功。送信を頼まれていないフォームは一度も送信しなかった
  • 本家jev-ultrafastは、公表値2.798秒のWikipediaのシナリオに4.3〜7.3秒かかった。入力値を作るモデルをOllamaにすると推論の無効化が伝わらず、遅く不安定になった
  • laya-ultrafastのJevモードは、Ollamaでも入力値の生成が速く安定した。ショップの並べ替えは1.2秒で終えた(Claude Code + Playwright MCPのSonnetは16.0秒)。成否は本家とほぼ同じだった
  • 詰まった原因の多くは判断の誤りではなく、ツール側のルール。パスワード欄の除外、入力後のEnterなし、日本語の渡し方は3構成に共通で、Layaモードでは同じラベルのボタンの取り違え、ASCII以外の文字を捨てる正規化、検索向きの完了条件が加わった

比べた構成

4つの構成と、以降で使う呼び方は次のとおりです。

呼び方 ツール 画面上の判断 入力値を作るモデル
Claude + PW MCP Claude Code + Playwright MCP Claude(Sonnet 5 / Opus 5.5) Claude
本家 jev-ultrafast Jev(TypeSafe API) Ollamaのgemma4
laya-Jev版 laya-ultrafast(DECISION_MODEL=typesafe) Jev(TypeSafe API) Ollamaのgemma4
Laya版 laya-ultrafast Laya(421M、Macでローカル実行) Ollamaのgemma4

Claude + PW MCPは、Claudeが操作ごとにツールを呼び、そのたびにページのスナップショットを読んで次の操作を決めます。

残りの3つは、プロンプトを1つ受け取ったら最後まで自分で進める単体のエージェントで、以降は「単体3構成」と呼びます。ページを番号付きの要素の一覧にして、どの要素にどの操作をするかを判断モデルに選ばせ、入力する文字列だけを小さなテキストモデルに作らせます。

単体3構成の入力値は、すべてOllamaのgemma4で作りました。本家はREADMEの手順と計測でOpenRouter経由のMercury 2.5を使っていて、laya-ultrafastのデフォルトもMercury 2.5ですが、今回は使っていません。

検証環境とシナリオ

項目 値
マシン MacBook Pro(Apple M1 Max、メモリ32GB)、macOS 26.5
ブラウザ Google Chrome 153.0.8010.53(検証専用プロファイル、実行ごとに作り直し)
Claude Code 2.1.281(claude -pで実行)
Playwright MCP @playwright/mcp 0.0.82
jev-ultrafast 1231850
laya-ultrafast 571431b、laya-mlx 0.1.0、チェックポイントaac6fef/laya-typed-decisions-mlx
Jev jev-latest(実行時はjev-1.13.0)
テキストモデル Ollama 0.34.3、gemma4:latest(8B、Q4_K_M)

比較したシナリオは次の14個です。公開サイトは、自動操作の練習用に公開されているサイトを選び、回数を少なくし、ダミーの情報だけを使いました。

  • ローカルのフォーム: 氏名・メール・国(select)・アカウント種別(ラジオ)・規約同意(チェックボックス)を入力する。英語版、日本語ラベルで値はローマ字の版、日本語ラベルで値も日本語の版、英語版のプロンプトに「送信まで」を足した版の4つ
  • ローカルのショップ: 価格の安い順に並べ替える、Backpackをカートに入れる、Backpackを買う手続きを確認画面まで進める、の3つ。6商品それぞれに同じ「Add to cart」ボタンがある
  • saucedemo: ログイン、チェックアウトの確認画面まで、並べ替え、の3つ
  • Wikipedia: 英語版で「Espresso」、日本語版で「エスプレッソ」、英語版で本家のREADMEと同じ「ゲーデルの不完全性定理」の記事を開く、の3つ
  • TodoMVC: ToDoを1件追加して完了にする

Claude + PW MCPは、英語フォーム・日本語フォーム・ショップのチェックアウトを3回、それ以外を1回動かしました。単体3構成は、各シナリオを2回ずつ(TodoMVCだけ1回)です。laya-ultrafastはテキストモデルをtemperature(出力のばらつきを決めるパラメーター)0で呼び、判断も確率が最大の選択肢を選ぶので、2回は結果の再現性を見る目的です。本家はtemperatureを指定しないので、2回の結果は分かれる場合があります。本家の公表値と比べるゲーデルのシナリオだけは、本家とlaya-Jev版を3回にしています。

成否は、ページ側の状態で判定しました。ローカルのページは入力値や遷移をサーバーに記録し、公開サイトは最終的なURLやページの内容を確認しています。

結果の一覧

シナリオごとの結果は次のとおりです。「送信」は、値は全部正しく入ったが、頼まれていない送信までした回です。「部分」は、一部の項目だけ正しく入った回です。

シナリオ PW MCP(Sonnet) PW MCP(Opus) 本家 laya-Jev版 Laya版
英語フォーム 成功 3/3 成功 3/3 送信 2/2 送信 2/2 送信 2/2
英語フォーム(送信まで) 成功 1/1 成功 1/1 成功 2/2 成功 2/2 成功 2/2
日本語ラベル・ローマ字の値 成功 1/1 成功 1/1 部分 1・送信 1/2 送信 2/2 部分 2/2
日本語フォーム 成功 3/3 成功 3/3 失敗 2/2 失敗 2/2 部分 2/2
ショップの並べ替え 成功 1/1 成功 1/1 成功 2/2 成功 2/2 成功 2/2
Backpackをカートへ 成功 1/1 成功 1/1 成功 2/2 成功 2/2 失敗 2/2
ショップのチェックアウト 成功 3/3 成功 3/3 成功 2/2 成功 2/2 失敗 2/2
saucedemo(3シナリオ) 成功 3/3 成功 3/3 失敗 6/6 失敗 6/6 失敗 6/6
Wikipedia英語 成功 1/1 成功 1/1 成功 2/2 成功 2/2 失敗 2/2
Wikipedia日本語 成功 1/1 成功 1/1 失敗 2/2 失敗 2/2 失敗 2/2
ゲーデルの不完全性定理 成功 1/1 成功 1/1 成功 3/3 成功 3/3 成功 2/2
TodoMVC 成功 1/1 成功 1/1 失敗 1/1 失敗 1/1 失敗 1/1

このほか、英語のプロンプトで日本語フォームを動かすシナリオも、単体3構成でだけ動かしています。結果は日本語フォームとほぼ同じでした。

Claude Code + Playwright MCPで動かす

Claude + PW MCPは、SonnetとOpusの計40回すべて成功しました。saucedemoは、Playwright MCPに自分でブラウザを起動させる構成で動かしました。既存のChromeにCDPで接続した構成では、ログイン後のクリックの届かない場合があったためです。

英語のフォームには、次のプロンプトを渡しました。送信するとは書いていません。

Fill in the contact form with full name Taro Yamada, email address taro@example.com, country Japan, account type Business, and agree to the terms of service.

Claude + PW MCPは、ページを開いてスナップショットを読み、フォームに入力して、もう一度スナップショットで確かめる4回の操作で終えました。そして「送信は依頼に含まれていないため押していません」と報告して止まりました。SonnetとOpusで計6回、日本語のフォームも含めると計12回、一度も送信していません。プロンプトに「then submit the form」と足すと、送信して成功しました。

同じ「Add to cart」ボタンが6つ並ぶショップでも、スナップショット上で「Backpackの行にあるAdd to cart」を特定して押していました。

作業時間(最初の判断から止まるまで)は、シナリオごとの中央値で15〜36秒です。これとは別に、Claude Codeとnpx経由のPlaywright MCPの起動に約12秒かかります。

本家jev-ultrafastを動かす

本家のREADMEは、Wikipediaでゲーデルの不完全性定理の記事を開く作業を2.798秒としています。同じプロンプトで動かすと、本家は3回とも記事を開き、作業時間は4.3〜7.3秒でした。

2回目(5.6秒)の内訳は、Jevの4回の呼び出しで2.4秒、gemma4の1回の呼び出しで1.9秒、残りのブラウザ操作などで1.3秒です。本家は、Google Flightsの計測の内訳として、Jevの1判断の中央値を178ミリ秒、Mercury 2.5の呼び出しを0.35〜0.58秒と公表しています。今回のJevは1判断あたり約0.6秒、gemma4は1回1.9秒で、どちらもそれより長くかかりました。Wikipediaの2.798秒の内訳は公表されていないので条件をそろえた比較はできませんが、差の大部分はこの2つだと見ています。

Jevの1判断が長い理由には、APIまでの距離があります。TypeSafe APIのホストはAWSのus-west-2(オレゴン)のIPアドレスで、東京からはTCP接続だけで約115ミリ秒かかりました。

Ollamaでは推論の無効化が伝わらない

本家では、gemma4の呼び出しが遅く不安定でした。入力値を作る呼び出しは中央値4.2秒かかり、25秒のタイムアウトで止まった回もあります。saucedemoの失敗6回のうち4回は、このタイムアウトか、テキストモデルが入力値を返さなかったことによるものです。

原因は、テキストモデルの呼び出し方でした。本家は推論の無効化をOpenRouter向けの書き方("reasoning": {"enabled": false})で送り、temperatureを指定しません。Ollama上のgemma4は、デフォルトで推論(thinking)が有効で、temperatureは1です。Ollamaは本家の指定を解釈しないので、gemma4はこのデフォルトのまま推論を走らせ、毎回違う値を返します。本家の書き方で同じ入力を3回送ると、応答時間は1.9〜11.5秒、推論の出力は0〜1,668文字で、返す値も毎回違いました。

パスワード欄が見えていない

saucedemoは、タイムアウトしなかった回もログインで失敗しました。原因はページの読み取り部分にあります。本家は、次の行でパスワード欄を操作対象から外しています(snapshot.js)。

const safe = e => !['password','file','hidden'].includes(e.type);

モデルからはパスワード欄が見えないので、ユーザー名の欄にstandard_userとsecret_sauceを交互に打ち込み続けていました。パスワードをモデルに渡さないための除外だと思われますが、READMEには書かれていません。ログイン画面をエージェントだけで通ることはできません。

ただし、本家とlaya-ultrafastは、リモートデバッグを有効にして起動しておいたChromeに接続し、その中に新しいタブを開いて動きます。普段使いのChromeに接続すれば、そのプロファイルのログイン状態をそのまま使えます。先に自分でログインしておけば、ログイン後の画面は操作できる可能性があります。今回は検証専用のプロファイルで起動したChromeに接続したので、この使い方は試していません。

フォームの送信とEnterキーの扱い

英語のフォームでは、本家は5項目を入力したあと、続けてSubmitを押して完了を宣言しました。JevがSubmitを選んだ確率は0.99です。

TodoMVCでは「Buy milk」を入力できたものの、Enterを送らないのでToDoを追加できず、入力欄のクリックを繰り返して止まりました。本家は、入力欄をクリックして文字列を挿入するだけで、入力後にキーを送りません。

日本語はエスケープされてテキストモデルに届く

日本語のフォームとWikipediaは一度も成功しませんでした。本家は、テキストモデルへのリクエストを作るとき、Pythonのjson.dumps()をデフォルトのまま使っています。デフォルトでは非ASCIIの文字が\u30a8のようなエスケープ列になるので、プロンプトの日本語はエスケープ列としてテキストモデルに届きます。Ollamaで推論が走る問題も重なって、「入力値を返さなかった」というエラーで止まる回がありました。日本語Wikipediaの検索語に「雨宮天」「奄美大島」のような関係のない語を入れ続けて、267秒かかった回もあります。

同じプロンプトを、エスケープせずUTF-8のまま渡すように手元で1行変えると、日本語Wikipediaは2回とも記事を開き、日本語フォームも全項目を正しく入力しました(送信もしましたが)。ただし、Mercuryでもこの読み違いが起きるかは確かめていません。大きなモデルなら、エスケープ列をそのまま読める可能性があります。

laya-ultrafastのJevモードに替える

laya-ultrafastは、DECISION_MODEL=typesafeを付けると判断役がJevになります。Jevに判断させる部分(model.pyのchoose()と質問文)と、ブラウザ操作(browser.py)は本家と同じコードです。違うのは、ページの読み取り(snapshot.jsで入力欄の説明を足している)と、テキストモデルの呼び出し方です。

laya-ultrafastは、ローカルのLLM向けに推論を無効化する指定(reasoning_effort=none)を送り、temperatureを0にしています。同じ入力を3回送ると、応答時間は0.8〜1.3秒で推論は走らず、毎回同じ値を返しました。gemma4の呼び出しの中央値は、本家の4.2秒に対して0.65秒です。タイムアウトで止まる回もなくなりました。

成否は本家とほぼ同じでした。ショップの並べ替えは1回の操作で終え、1.2秒で止まりました。英語フォームはやはり入力後にSubmitを押しました。saucedemoでユーザー名の欄にパスワードまで打ち込むのも、TodoMVCで入力欄のクリックを繰り返すのも同じです。パスワード欄の除外とEnterなしは、本家と同じコードです。

日本語も、本家と同じくエスケープ列のままテキストモデルに届きます。gemma4は日本語Wikipediaの検索語として「Wikipedia」を返し、日本語フォームの氏名の欄にメールアドレスを返しました。UTF-8のまま渡すように直すと、日本語フォームは全項目を正しく入力してから送信し、日本語Wikipediaも2回の操作で記事を開いて完了しました。Jev自体は日本語のページでも判断できています。

Ollamaで動かすなら、本家よりlaya-ultrafastのJevモードのほうが扱いやすいです。

laya-ultrafastをLayaで動かす

最後に、判断役をLayaに替えてMacだけで動かしました。Layaの1判断は中央値56ミリ秒で、Jevの0.4〜0.6秒よりずっと短く済みます。そのぶん入力値を作るgemma4の呼び出しの割合が大きく、英語フォームでは作業時間5.0秒のうち2.8秒がgemma4でした。

ただし成功したシナリオは、ショップの並べ替え、送信までを指示した英語フォーム、ゲーデルの記事の3つだけでした。Laya版は、判断を細かい質問に分けてLayaに尋ね、残りをコードのルールで決めます。崩れ方の多くは、このルールの前提から外れたときに起きていました。

同じラベルのボタンを区別できない

「Backpackをカートへ」では、2回ともBolt T-Shirtを入れました。Laya版は、タスク開始時にテキストモデルへ計画を作らせ、「Add to cart = Backpack」のような要件にしてからLayaに尋ねます。Layaから見えるのは同じ「Add to cart」ボタン6個で、Backpackの行のものを選べませんでした。

完了とみなす条件が検索向き

英語フォームでは、Laya版も5項目を正しく入力してからSubmitを押しました。計画の完了条件は「The contact form is submitted with the provided details.」でした。プロンプトに送信の指示がなくても、フォームなら送信して終わるものとして計画されていました。

送信したあとも止まらず、アカウント種別のラジオを「Individual」と「Business」で往復してから、行き詰まりとして終了しました。Laya版は、「今のページは指示を満たしているか」をLayaに尋ねたうえで、コードの条件で完了を決めます。その条件は次のとおりです(laya_ultrafast/laya.py)。

laya_done = done["choice"] in {"finish", "results"}
if (not reqs and done["choice"] == "finish") or (
    searched and (len(matching) >= 2 or (laya_done and self.waits >= MAX_RESULT_WAITS))
):
    return "DONE", None, None, None, "done", None, None

完了になるのは、入力する値(reqs)が1つもなくLayaが「finish」と答えた場合か、送信で別のページに移って結果が見えた場合(searched)だけです。フォームに値を入れて同じページにとどまる作業は、どちらにも当てはまりません。英語フォームでは、Layaは「finish」と4回答えていました(確率0.40)。それでも完了にならなかったのは、この条件のためです。検索して結果を開く、READMEのデモのような作業を想定した条件のようです。

ショップの並べ替えでも同じことが起きました。Laya版は最初の操作で正しく並べ替えたのに、そのあとカートに商品を入れたり外したりを10回続けてから止まりました。最終的な並び順は正しいので成功と判定しましたが、途中でカートを触っています。Jevモードでは操作の選択肢にDONEがあり、Jevが自分で選べるので、この問題は起きませんでした。

日本語が空文字になる

日本語のページでは、テキストモデルへの渡し方に加えて、Laya版だけにある文字列の正規化でも崩れます(laya_ultrafast/laya.py)。

def fold(text):
    text = unicodedata.normalize("NFKD", str(text)).encode("ascii", "ignore").decode().lower()
    return re.sub(r"[^a-z0-9]+", " ", text).strip()

ASCIIに変換できない文字を捨てるので、日本語はすべて空文字になります。fold("神奈川県")とfold("東京都")は、どちらも""です。Laya版は、入力したい値と選択肢や入力欄の中身を、このfold()を通して比べています。

テキストモデルへの渡し方をUTF-8に直したうえで日本語フォームを動かすと、計画は「氏名=山田太郎、都道府県=神奈川県」と正しくできていました。それでもLaya版は、都道府県のselectで「北海道」と「選択してください」を往復し、氏名は一度も入力しませんでした。「山田太郎」も日本語の選択肢も空文字になり、コード上は完全一致とみなされて、氏名の値が都道府県のselectに割り当てられたためです。このときのログには確率1.0と出ていますが、これはコードの分岐で決まった値です。

日本語Wikipediaでは、検索欄に「エスプレッソ」を3回打ち直してから止まりました。入力済みの値も空文字になるので、「まだ入力されていない」と判定され続けています。

このほか、英語Wikipediaでは2回とも記事までは開いたものの、止まらずにリンクを押し続けて失敗しました。2回目は出典のリンクから外部の通販サイトまで移っています。TodoMVCでは、見出しの「TodoMVC」リンクから別のサイトへ移って、60操作の上限で止まりました。

作業時間と費用

作業時間は、成功した回に限ると単体3構成が1.1〜13.5秒で、多くは8秒以内でした。Claude + PW MCPは中央値で15〜36秒、これに起動の約12秒が加わります。ただし単体3構成は失敗した回に長くかかることがあり、本家の日本語Wikipediaでは267秒でした。

Jevの費用は、判断ログの入力トークン数に公表単価(入力100万トークンあたり0.042 USD、出力は無料)を掛けて出しました。1シナリオあたり0.0001〜0.0089 USD、中央値0.0007 USDです。Claude Codeは1回0.037〜0.20 USDで、合計はSonnet 5の20回で1.16 USD、Opus 5.5の20回で1.85 USDです。Laya版は判断とテキストモデルの両方が手元のMacで動くので、APIの費用はかかりません。

まとめ

2026年9月24日時点の版で動かすと、Claude Code + Playwright MCPと単体3構成では、得意なところと足りないところが分かれました。

Claude Code + Playwright MCPは、操作のたびにページを読み直して進むので、同じラベルのボタンが並ぶ画面、日本語のページ、ログイン画面でも止まりませんでした。プロンプトにない送信もしていません。そのぶん1回に15〜36秒かかり、起動に約12秒、費用も1回あたり0.037〜0.20 USDかかります。

jev-ultrafastとlaya-ultrafastは、ログインの操作がない英語のページで「検索して開く」「並べ替える」「カートに入れる」といった流れなら、数秒で終わりました。Jevの費用は1シナリオあたり1セント未満で、Layaモードなら判断がMacの中で完結します。足りていないのは、パスワード欄、入力後のEnterキー、日本語の扱いといった、判断モデルの外側の部分です。フォームでは、プロンプトになくても送信まで進みます。入力値を作るモデルにOllamaを使う場合は、laya-ultrafastの呼び出し方のほうがかみ合いました。どちらも公開から1〜2週間のツールで、今回コードで特定した原因は、改修で変わる可能性があります。

この記事をシェアする

関連記事