「実装できました」が、ブラウザで開くと動いていない ── AI エージェントの E2E QA を「実装者と評価者の分離」で自律ループ化した話【株式会社ライトコード】
この記事で分かること
- AI エージェントに実装を任せたとき、なぜ「実装できました」を鵜呑みにできないのか
- そこで自動 QA をワークフローに組み込んだら、今度は人間が毎回はさまる面倒 が生まれた話
- その面倒を消すために作った、実装したら勝手に検証→修正→再検証が回る自律 QA ループの設計
- 実際に 1 画面でパイロットして分かった、ハマりどころと教訓(失敗込みの実録)
この記事は、私たちが実際にたどった道のりを 4幕の物語 として書いています。「動かない」→「自動 QA を入れた」→「でも人間が毎回はさまる」→「自動で回るようにした」という、私たちがたどった順序そのものです。
- 第1幕:「実装できました」が動かない → ブラウザで動作確認させる(最初の自動 QA)
- 第2幕:QA は入った。でも人間が毎回はさまる → 中核の判断「作り手と採点者を分ける」
- 第3幕:その判断を Claude Code で組む(実装リファレンス)
- 第4幕:1画面でパイロット → ハマりどころと教訓(失敗込みの実録)
対象読者・前提・動作環境
📌 想定する読者
- Claude Code などの AI コーディングエージェントを業務開発で使っている方
- エージェントの「実装できました」を信用しきれず、QA の自動化を考えている方
- サブエージェント/スキルといった Claude Code の構成要素に一通り触れたことがある方
第1幕:「実装できました」を、ブラウザで開くと動いていない
私たちのチームでは、機能実装を AI エージェント(Claude Code)に任せる場面が増えました。エージェントは「実装できました」と言ってきます。型チェックも Lint も通っている。でも、実際にブラウザで開いてみると、期待通りに動いていない ── これが頻繁に起きました。
- 画面のレイアウトが崩れている
- フォームが送信できない
- コンソールにエラーが出ている
- ある操作をすると 500 が返る
不思議なことではありません。型チェックや Lint が見ているのは「どう書かれているか」であって、「実際に動かしたとき、ユーザーが必要とする振る舞いをするか」ではないからです。
この「振る舞いの正しさ(Behaviour)の検証」が、実はソフトウェア検証の中で最も遅れている領域です。Thoughtworks の Birgitta Böckeler は AI エージェント向けのハーネス(=エージェントを取り巻く仕組みの総体。後述します)を論じる中で、ハーネスが規制する対象を保守性 / アーキテクチャ適合性 / 振る舞いの3つに分け、振る舞いの検証こそが一番未成熟だと指摘し、これを「部屋の中の象」と呼びました。保守性や型は機械で速く検証できるのに、「本当にユーザーの役に立つ動きをするか」は誰も自動で確かめられていない、というわけです。
さらに厄介なのが、実装した本人のセルフチェックは当てにならないという点です。人間のセルフレビューに「自分のコードは正しく見える」バイアスがあるのと同じで、「こう実装したのだから、こう動くはず」という前提が確認をすり抜けさせます。これは人間でもエージェントでも同じです。
そこで私たちは、Claude に実際にブラウザを操作させて E2E 動作確認させる仕組みをワークフローに組み込みました。これが最初の一歩です。
自動 QA の土台:エージェントがブラウザを操作できる状態を作る
AI エージェントにブラウザ E2E を任せるには、その下に「このアプリで E2E をどう動かすか」を教える基盤が要ります。要点はこうです。
- テスト専用ログイン。 本番は OAuth ログインですが、自動テストでこれを通すのは非現実的です。そこで開発/テスト環境でのみ有効なテストログイン用エンドポイントを用意し、本番では絶対に有効化されないよう環境変数でガードします。
- テスト DB の分離とリセット。 導入初期の最大の敵はテストデータ汚染でした。前のテストが残したデータで次が落ちる・通るが不安定になる、という典型です。対策は単純で、専用のテスト DB を本番/開発から分離し、各検証の前に必ずリセットすることです。
- factory CLI でのデータ投入。リセット後、シナリオに必要なデータを投入する CLI ツールを作成しました。作成したエンティティの ID を JSON で返すのが肝で、エージェントが ID をパースして URL 組み立てやクリーンアップに使えます。
- Reconnaissance-Then-Action(観察してから操作)。「見えない状態で操作する」と必ず失敗します。毎アクションの前に DOM スナップショットで現在の状態を確認し、正しい要素にだけ操作します。セレクタは
data-testidを最優先にして、スタイル変更に強くしておきます。
これらをプロジェクト固有のスキルとして「手順」だけでなく「なぜそうするか」まで明文化し、汎用の QA コマンドと組み合わせます。こうして「実装直後にブラウザで動作確認する」が、ようやく回るようになりました。
💡第1幕の結論:自動 QA は前進だった。「実装できました」を、機械が実際に動かして裏取りできるようになったのです。── ただ、運用してみると、今度は別の問題が前面に出てきました。
第2幕:QA は入った。だが、人間が毎回はさまる ── 中核の判断「作り手と採点者を分ける」
運用してみると、すぐに別の不満が生まれました。「自動 QA」と呼ぶには、人間が何度も手で介在していたのです。
具体的には、実装が1つ終わるたびに、こういう往復が発生しました。
- 起動の手間。 実装が完了しても、人間が明示的に「QA を実行して」とコマンドを打たないと、検証が始まらない。
- 修正依頼の手間。検証結果が返ってきたら、人間がそれを読んで「このバグを直して」と都度エージェントに指示する。直ったら、また「もう一回 QA して」と打つ。
つまり実装 → QA → 修正 → 再 QA というフィードバックループが、毎周、人間の手で分断されていたのです。小さな変更ほど、この往復のオーバーヘッドが本体の作業より重く感じられました。「動作確認、して」「直して」「もう一回確認して」を一日に何度も打つのは、地味に消耗します。
加えて、構造的な問題もありました。検証を実装と同じ会話(同じ文脈) で走らせると、実装したエージェントが自分の成果物を採点する形になりがちです。第1幕で触れたセルフ評価バイアスが、ここで再び顔を出します。「こう実装したのだから正しいはず」という前提が、検証に混入してしまうのです。
ここまでで、消すべき介在が3つ見えてきます。
- 起動の介在 … 人間が
/qa(ブラウザ上でQAを実行するSkill)を打たないと検証が始まらない - 修正依頼の介在 … 人間が「直して」と都度頼まないと修正が進まない
- セルフ評価バイアス … 実装した本人(の文脈)が自分を採点し、バイアスを混入させる
この「人間が毎周はさまる」状態は、実はもっと大きな潮流から見ると不自然です。OpenAI はエージェントファーストな開発について、人間の役割は「コードを書く人」から「環境・意図・フィードバックループを設計する人」へ移ると述べています。そしてエージェントは、自分の変更をレビューし、追加のレビューを要求し、フィードバックに対応し、全レビュアーが満足するまで自律的にループ反復して仕事を仕上げる ── と。
同じ記事にある「修正は安価、待機は高コスト」という言葉も刺さりました。人間が間に立ってエージェントを待たせるより、エージェントにフィードバックループを回させた方がずっと速いのです。
つまり、起動も、修正依頼も、採点も、人間の手から外したい。ところが、ただ「人間を抜く」だけでは評価者が消えません。実装したエージェントにそのまま採点させれば、バイアスが残るからです。ここで、このシステム全体を決めるたった一つの設計判断 が要ります。
中核の判断:作り手と採点者を分ける
一番大事な判断は、これだけです。
コードを書くエージェント(Generator)と、それを採点するエージェント(Evaluator)を、別々の文脈に分離する。
これは Anthropic が長時間実行アプリ向けのハーネス設計で提唱する、GAN(敵対的生成ネットワーク)に着想を得た生成者 (Generator) – 評価者 (Evaluator) 分離の考え方そのものです。彼らは、エージェントの自己評価は信頼できない ── 自分の成果物を評価させると、人間の目には明らかに平凡な出力でも自信たっぷりに称賛しがちだ ── と指摘し、外部の評価エージェントが実際にライブのページを操作してから採点し、生成者に具体的な反復対象を与える設計を示しています。
これを QA に当てはめ、評価者(Evaluator)はこう動かします。
- 実装役(Generator)とは別の隔離されたコンテキスト で起動する
- 実装の差分も、「なぜこう直したか」という意図も渡さない
- 受け入れ基準と、対象画面・URL だけを渡す
- 「実装者の意図」ではなく「受け入れ基準」だけに照らして、初見のユーザーのように動くアプリを評価する
意図を渡さなければ、バイアスは混入しようがありません。これがセルフ評価バイアスを構造的に消す仕掛けです。そして両者の受け渡しは、会話の往復ではなく構造化されたレポート(JSON)1枚 に固定します(Anthropic の「ファイルベース通信」)。Evaluator は書くだけ、Generator は読んで直すだけです。
💡第2幕の結論:中核の判断は決まった。作り手と採点者を別々の文脈に分け、受け渡しは JSON レポート1枚に固定する ── これで3つの介在のうちセルフ評価バイアスは、構造的に消えます。残る「起動の介在」「修正依頼の介在」を実際に消すのは、この判断を動く形にする実装の仕事です。次の幕で組み立てます。ちなみに0の行のpageのレンダリング結果以外のところや他の行には、MetaデータやNext.jsの必須のClient Componentの情報などが入ってるようでした。
第3幕:その判断を Claude Code で組む(実装リファレンス)
第2幕で決めた「作り手と採点者の分離」を、Claude Code の機能(スキル/サブエージェント)で実際に組みます。やることは、第2幕で残った2つの介在 ──起動と修正依頼── を実装で消し、分離を支える周辺の仕掛け(受け入れ基準の供給/受け渡し契約/暴走防止)を整えることです。設計にあたっては、公開されているハーネスエンジニアリングの議論(OpenAI / Anthropic / Böckeler)を参考にしました。
アーキテクチャ全体像
まず設計の全体像です。第2幕の「分離」を、実装と検証が1本のループで回る形に落とすと、こうなります。
…
記事の続きは下のURLをクリック!
https://rightcode.co.jp/blogs/55983
もっとワクワクしたいあなたへ
現在、ライトコードでは「WEBエンジニア」「モバイルエンジニア」「データエンジニア」「ゲームエンジニア」「デザイナー」「WEBディレクター」「営業」などを積極採用中です!
ライトコードは技術力に定評のある受託開発をメインにしているIT企業です。
有名WEBサービスやアプリの受託開発などの企画、開発案件が目白押しの状況です。
- もっと大きなことに挑戦したい!
- エンジニアとしてもっと成長したい!
- モダンな技術に触れたい!
現状に満足していない方は、まずは、エンジニアとしても第一線を走り続ける弊社代表と気軽にお話してみませんか?
ネット上では、ちょっとユルそうな会社に感じると思いますが(笑)、
実は技術力に定評があり、沢山の実績を残している会社ということをお伝えしたいと思っております。
- ライトコードの魅力を知っていただきたい!
- 社風や文化なども知っていただきたい!
- 技術に対して熱意のある方に入社していただきたい!
一度、【Wantedly内の弊社ページ】をのぞいてみてください。