TabbitBlog

Claude Agent SDK のブラウザツールを Playwright で試す

ローカルのサンプルで、成功、ボタンの欠落、呼び出し上限を API キーなしで確認します。

この記事の内容
  1. ブラウザの接続方法を選ぶ
  2. 登録、実行、タスク結果を分ける
  3. 三つのツールを実装する
  4. 実行順にソースを読む
  5. ローカルで実行する
  6. 正常系と異常系をたどる
  7. ツールの結果を読む
  8. 実行する場所で操作を制限する
  9. 停止条件を決める
  10. セレクターを変える前に調べる
  11. モデルの外で結果を検証する
  12. 小さい作業から移す

Claude Agent SDK はエージェントのループを実行し、MCP 経由でツールを呼び出します。ブラウザの起動と結果の確認はハンドラーの役割です。この例の完了条件は、ローカルページにステータスコードが表示されることです。

ブラウザの接続方法を選ぶ

入力と完了条件が分かっている定型作業には、用途を絞ったツールが適しています。未知の画面の探索には汎用の Playwright MCP が便利です。Anthropic の API SDK が提供するブラウザ用ツールセットには、別のドライバーインターフェースがあります。

API SDK のツールセットガイド · Playwright のガイド

ブラウザエージェント · ブラウザ自動化 · 自動化エージェント

登録、実行、タスク結果を分ける

MCP クライアントに三つの短い名前が表示されれば登録はできています。次に URL と状態を見て、ハンドラーがどのページを使ったかを確認します。最後にホストが別の読み取りで完了条件を検証します。問題が起きたら、この順番で調べます。

三つのツールを実装する

tool() で入力検証とハンドラーを定義し、createSdkMcpServer() で登録します。オプションのエージェントはサーバーを query().options.mcpServers.fixture に渡します。操作名は mcp__fixture__reveal_status になります。許可には完全な名前を使い、各ハンドラーでも操作範囲を制限します。 SDK カスタムツールガイド

Playwright はログイン情報のない新しいコンテキストを開きます。入力は二つのモードに限り、ナビゲーションはテストページと同じオリジンに制限します。アクセシブルなボタン名で完全一致を探し、一件だけならクリックし、ステータス領域を読み取ります。

ツール確認した結果
open_fixture({variant})Status code hidden
read_status()ページの状態の読み取り
reveal_status()Status code: SDK-17
クリック後に確認した状態

ブラウザエージェントの安全性 · 仮想ブラウザ

実行順にソースを読む

fixture.mjs で二種類のテストページを確認します。browser-tools.mjs ではロール指定のセレクター、状態の読み取り、呼び出し上限を探し、次に smoke.mjs を読みます。メモリ内の MCP クライアントは、任意のエージェントと同じハンドラーを呼び出します。先にこのテストを使うとモデル側とツール側を分けて調べられます。

ローカルで実行する

スモークテストは、SDK が作成した MCP サーバーに決定的なクライアントをメモリ内通信で接続し、ローカルの Chromium を操作します。モデル認証情報なしで実行しました。任意のエージェント用エントリには認可されたキーが必要で、今回は実行していません。

サンプルプロジェクトをダウンロード

npm ci
npx playwright install chromium
npm test

正常系と異常系をたどる

一回目で通常ページを開き、二回目でコードを表示し、三回目で読み取ります。次にボタンのないページを開き、操作が失敗することと、別の読み取りでもコードが非表示であることを確認します。残りの呼び出しは読み取りだけで上限に到達します。

ツールの結果を読む

異常系のページではボタンを取り除いています。ツールは一致件数ゼロとコードが非表示であることを報告します。別の読み取りでも同じ状態を確認しました。九回目の呼び出しは上限エラーになります。画像はページの状態を示し、JSON はツールの戻り値を記録します。

{
  "isError": true,
  "ok": false,
  "code": "TARGET_MISSING_OR_AMBIGUOUS",
  "expected": "Reveal status code",
  "matches": 0,
  "observed": "Status code hidden"
}
ボタンがなくコードが非表示のテストページ

実行する場所で操作を制限する

この例には一つのローカルオリジン、二つのモード、一つのボタンがあります。ページを置き換えるときも同じ程度に範囲を絞ります。ページ上の文はデータであり、ツールの許可は変えられません。ページから受け取ったセレクター、スクリプト、移動先をそのまま実行せず、書き込み時は許可する項目と環境を先に決めます。

停止条件を決める

対象がない場合や複数ある場合は、ページの状態を残してセレクターを調べます。クリック後に表示が更新されなければ、再試行の前に状態を読み取ります。上限に達したら処理を終了し、最後に確認できた結果を残します。書き込みを再試行する前に、保存済みの値を確認します。

失敗次の手順
TARGET_MISSING_OR_AMBIGUOUSセレクターを見直す
POSTCONDITION_FAILEDページを読み直す
TOOL_BUDGET_EXHAUSTED停止して確認済み結果を残す

Claude Code の利用者から、ブラウザが動いていないのにフォームのテストが成功と報告されたという声がありました。別の議論では、検証エラーの表示と次の操作が行われていないことの両方を確認する提案がありました。この例にも独立した確認を入れています。 r/ClaudeCode · r/AI_Agents

初回タスクの確認項目 · DevTools でのデバッグ

セレクターを変える前に調べる

読み取り失敗には、ページが開いていない、対象がない、クリック後にアプリが状態を変えなかった、という別々の原因があります。エラーコードと観測状態を残します。クライアントで再現できる場合は、モデルの指示を変える前にハンドラーかテストページを修正します。

モデルの外で結果を検証する

任意のエントリは組み込みツールを無効化し、三つのツール名だけを許可します。ターン数と時間にも上限があります。モデルが成功を報告しても、ホストが別にページを検証します。応用時には、再読み込み後の保存値を確認するなど、単独で実行できる検証を加えます。

npm run agent

エージェントの推論

小さい作業から移す

テスト用オリジンに切り替え、コード表示を一つの業務上の完了条件に置き換えます。入力を絞り、呼び出し上限を維持します。ログには操作名、固定のエラーコード、検証結果の要約だけを残します。認証情報やフォームの生データを共有せず、小さい手順を検証してから操作範囲を広げます。

よくある質問

どのコンポーネントがブラウザを起動しますか?

ツールをホストするプロセス内のローカル Playwright アダプターです。

スモークテストに API キーは必要ですか?

不要です。クライアントが SDK に登録したツールを直接呼び出します。

任意の URL を渡せますか?

サンプルが受け付ける入力は二つのモードです。移動先は同じローカルオリジンに制限します。

クリック後の確認はなぜ必要ですか?

ブラウザがクリックを受け付けても、アプリが目的の状態に変わるとは限らないためです。

Playwright MCP とはどう違いますか?

汎用サーバーは再利用可能なブラウザ操作を提供します。この例の三つのツールは一つの作業に特化しています。

本番フォームに使えますか?

最初にテストページを使い、本番へ接続する前に書き込み権限と独立した検証を定義します。

次のステップへ

Tabbit と一緒に仕事をしましょう。

タブをまたいで調査し、繰り返しのブラウザ作業を自動化し、あらゆる文脈を手の届くところに。