📌 2026-04-10 追記: helix-agent はその後も進化しています
本記事執筆時のバージョンは v0.13.0 (Tools 20 + Resources 3 + Prompts 3 / 322 テスト) でしたが、現在は v0.15.1 / 27 MCPツール / 347 テスト です:
- 4層コードレビューパイプライン (gemma4 → Sonnet → Opus → Codex、P1≥3 で自動 xhigh エスカレーション)
- parallel_tasks (2軸モデル選定、5並列 51秒/10GB VRAM)
- 部門別 RAG (
dept_search/dept_store、5部門 1,419 points)- 自律運用基盤 (9 デーモン + audit→dispatch→heal 自動修復)
- retry_guard、critical_files_guard (SHA-256 監視)
困っていたこと
Claude Code で転職サイトのプロフィールを自動更新しようとすると、Wantedly や LinkedIn の入力欄で typed text が即座に消える という現象に3週間悩まされていました。
# Playwright MCP 経由
await page.fill('textarea[name="intro"]', "自己紹介...")
# ↑ 入力されるが、1秒後にはReactが元の値に戻す
正体は React Controlled Component。value 属性を React state が完全管理しているので、DOM経由で値を書き換えても state に反映されず、次の再レンダリングで元に戻ります。
試して効かなかった方法
| 方法 | 結果 |
|---|---|
Playwright fill
|
値が戻る |
Playwright type(1文字ずつ) |
同上 |
evaluate で input.value = '...' 代入 |
同上 |
execCommand('insertText') |
部分的に成功(フォーカス外した瞬間戻ることあり) |
| React Fiberを直接操作する hack | 保守不能 |
効いた方法:agent-browser の fill
Vercelが公開した agent-browser(Rust/CDP)の fill コマンドは、KeyboardEvent / InputEvent を DevTools Protocol 経由で dispatch します。これは「人間がキーを叩いた」のと区別がつかないため、Reactのイベントハンドラが正常に発火します。
agent-browser fill 'textarea[name="intro"]' "自己紹介..." --session my-session
# → Reactのonchange/onInputハンドラが発火、state更新
helix-agent v0.13.0 で MCP 化した
手動で agent-browser CLI を叩くのは面倒なので、自作の helix-agent MCP サーバーに統合しました。v0.13.0 では Anthropic Academy MCP公式パターンに完全準拠(Tools 20 + Resources 3 + Prompts 3)。
Claude Code 側からは:
computer_use(action="type", selector='textarea[name="intro"]', text="...")
これを呼ぶと内部で agent-browser fill が実行されます。優先順位は agent-browser → helix-pilot → Playwright にフォールバック。
ついでのご褒美:トークン消費 82-93% 削減
agent-browserはアクセシビリティツリーを返すため、Playwrightの「スクリーンショット + DOM全取得」に比べて桁違いに軽量です。
50件同一フローで計測:
| Playwright | agent-browser | 削減率 | |
|---|---|---|---|
| 中央値 | 15,200 tok/action | 2,100 tok/action | 86% |
| p95 | 28,000 tok/action | 4,700 tok/action | 83% |
Windowsでの落とし穴
npm install -g agent-browser で入るのは .cmd ラッパーです。Python asyncio.create_subprocess_exec では .cmd は起動できないため、Windowsだけ create_subprocess_shell に分岐が必要です:
import sys, asyncio
if sys.platform == "win32":
proc = await asyncio.create_subprocess_shell(
f'agent-browser fill "{sel}" "{text}" --session {name} --json',
stdout=asyncio.subprocess.PIPE,
)
else:
proc = await asyncio.create_subprocess_exec(
"agent-browser", "fill", sel, text, "--session", name, "--json",
stdout=asyncio.subprocess.PIPE,
)
まとめ
- React Controlled Component問題は、DevTools Protocol のネイティブキーボードイベントで根本解決
- agent-browserは Rust/CDP で軽量、Windows では .cmd 経由で起動
- helix-agent v0.13.0 で MCP 化済、computer_use から自動的に選択される
- ついでに トークン消費 82-93% 削減
- MCP 3プリミティブ完全対応(Anthropic Academy準拠)
リポジトリ:https://github.com/tsunamayo7/helix-agent (MIT)
Claude Code でブラウザ自動化をしている人は、Playwright MCP から乗り換える価値があります。