[開発者向け]Agents CLIの評価コマンドで回すAIエージェント品質改善ループ

目次

はじめに

 GoogleはDevelopers Blogで、Agents CLIの評価機能を使った品質改善の進め方を紹介しました。初回評価から劣化の検出、モデル切り替えの比較、定期実行とアラートまでを実例で示しています。以下では、その流れと使い方を整理します。

参考記事

要点

  • Agents CLIのevalコマンド群は、生成・採点・比較・分析・プロンプト最適化で構成される。
  • Googleの実例では、誤ったシステムプロンプトの混入で平均スコアが4.0から2.75に下がった。
  • モデル切り替えでも平均は同じ幅で下がったが、低下の大半は1ケースに集中していた。
  • スケジューラーは同梱されず、cronやCloud Schedulerなど既存の仕組みと組み合わせる。
  • eval optimizeはADKプロジェクト向けで、LangChain拡張には現時点で対応していない。

詳細解説

Agents CLIの評価機能とは

 Googleによると、デモで動くエージェントを作ることと、動き続けるエージェントを保つことは別の課題です。後者では、モデル更新やツールの変更、新しい会話の形に耐える必要があります。

 そこでチームは、テストケースを実行して採点し、失敗を読んで直す作業を繰り返します。スコアが上がれば変更を残し、下がれば戻します。品質工学では、この進め方をヒルクライミング(山登り法)と呼びます。

 Agents CLIの`eval`コマンド群は、このループを前提に作られています。各コマンドは小さく、特定のフレームワークに依存しません。

  • `eval generate`:データセットの各ケースに対してエージェントを実行する
  • `eval grade`:生成されたトレースを採点する
  • `eval compare`:2回分の結果を並べて差分を出す
  • `eval analyze`:失敗をテーマごとにまとめる
  • `eval optimize`:プロンプトの自動改善を山登り的に実行する

 トレース(trace)は、入力を受けてからツールを呼び、応答するまでの実行記録です。何を「上」とみなすかは、データセットと採点基準の設計で決まります。

まず試す手順と初回評価

 セットアップからプロジェクト作成、初回の評価実行までを数コマンドで行えます。

uvx google-agents-cli setup

agents-cli create my-agent

cd my-agent && agents-cli install

agents-cli eval generate --dataset tests/eval/datasets/basic-dataset.json \

    -o tests/eval/output/

agents-cli eval grade --traces tests/eval/output/eval_dataset_*.json \

    --config tests/eval/eval_config.yaml

 `uvx`は、Python製のツールを一時的な環境で実行するuvのコマンドです。コマンドの全体はAgents CLIのコマンドリファレンスにあります。ソースコードはGitHubのgoogle/agents-cliリポジトリで公開されています。

 Googleの実例は、Agents CLI v1.8.0に同梱のLangChainテンプレートが土台です。テンプレートには、評価用のファイルが3つ含まれます。

  • `tests/eval/datasets/basic-dataset.json`:評価ケースのデータセット
  • `tests/eval/eval_config.yaml`:実行する指標の設定
  • `tests/eval/response_quality.py`:LLM-as-judge方式の独自指標

 LLM-as-judgeは、別のLLMに応答を採点させる方式です。設定ファイルでは、実行する指標を次のように宣言します。

# tests/eval/eval_config.yaml

metrics_to_run:

  - custom_response_quality

custom_metrics:

  - name: custom_response_quality

    custom_function_file: response_quality.py

 この指標は、正確さ・関連性・明快さの観点で各応答を1〜5点で採点します。採点役のモデルは`gemini-3.8-flash`です。

 初期のデータセットは1ケースだけのため、実例では4ケースに増やしています。

  • `greeting`:「hello」とあいさつする
  • `sf_weather`:サンフランシスコの天気を聞く。モックのツールが「霧」を返す
  • `rome_weather`:ローマの天気を聞く。ツールが既定の応答で返す都市
  • `off_topic`:2024年のワールドシリーズ優勝チームを聞く対象外の質問

 データセットは意図的に小さく、変更のたびに実行できる規模に保ちます。

 初回評価では4ケースすべてが有効で、エラーは0件でした。平均は5点中4.0、標準偏差は1.41です。結果はJSONとHTMLで`artifacts/grade_results/`に保存されます。

 Googleは、ばらつきがあること自体を健全な出発点と捉えています。全ケースが5.0なら、データセットが易しすぎる可能性が高いからです。ただし4ケースと少ないため、1ケースの変化で平均は大きく動きます。

プロンプトの劣化をケース単位で捉える

 次に、別のコードベース用のシステムプロンプトを誤って貼った想定で劣化を再現しています。変更は`app/agent.py`の`system_prompt`の1か所だけです。中身は、プロのシェフとして応答し、最後に必ずレシピを提案するものです。

 この変更はコンパイルが通り、エージェントも動きます。lint、単体テスト、型チェックでは検出できません。再評価すると、平均は4.0から2.75に下がり、標準偏差は0.96に縮まりました。文字列1つの差分に見えるため、レビューを素通りしやすい劣化です。

 2回分の結果は`eval compare`で比べます。基準と比較対象の結果ファイルを順に渡します。

agents-cli eval compare \

    artifacts/grade_results/results_20261003_224516.json \

    artifacts/grade_results/results_20261003_225158.json

 出力はJSONで、`changed_keys`と`unchanged_keys`が並びます。ケースごとの値は`differences`に入ります。`jq`や小さなPythonスクリプトで必要な値を抜き出せます。

 ケースごとのスコアを並べると、劣化の場所が分かります。

  • `greeting`:5.0 → 4.0。あいさつの後に頼まれていないレシピを紹介した
  • `sf_weather`:4.0 → 2.0。天気ツールを無視し、天気を作り話で答えた
  • `rome_weather`:2.0 → 2.0。ベースラインから作り話の応答だった
  • `off_topic`:5.0 → 3.0。質問には答えたが、レシピを付け足した

 最も重要なのは`sf_weather`です。シェフのペルソナが注意を`get_weather`ツールから逸らしました。その結果、ツールを呼ばずに天気を作るようになりました。ツールは登録されたままで、単体テストでは捉えられません。文脈の中で応答を採点するエンドツーエンドの評価でのみ表に出ます。

 平均の低下は明確な合図です。ただし、どこを直すべきかを示すのはケースごとの内訳です。

モデル切り替えは平均だけで判断しない

 より安く速いモデルで十分かは、よく出る問いです。実例では、プロンプトを元に戻して再評価しました。`app/agent.py`の`LLM = “gemini-3.8-flash”`を`gemini-2.5-flash`に替えています。

 平均は4.00から2.75に下がり、シェフのプロンプトと同じ幅でした。しかし内訳はまったく異なります。

  • `greeting`:5.0 → 5.0(変化なし)
  • `sf_weather`:4.0 → 3.0(言い回しがやや洗練されていない)
  • `rome_weather`:2.0 → 2.0(変化なし)
  • `off_topic`:5.0 → 1.0(大きく低下)

 低下の大半は`off_topic`です。安価なモデルは、その出来事が「まだ起きていない」と留保して回答を避けました。学習データの期限(トレーニングカットオフ)に由来する反応で、採点モデルは厳しく評価しました。

 内訳を見れば、大半の処理には妥当な代替だと分かります。弱いのは、最近の出来事に関する範囲外の質問だけです。本番の質問が前の3ケースに近ければ切り替えを検討できます。`off_topic`型が多ければ見送りという判断になります。

 注意点は2つです。

  • モデルとプロンプトは影響し合う。比べるべきは、各モデル向けに調整したプロンプトとの組み合わせ同士である
  • 採点ではVertex AI Eval Serviceが採点モデルを呼ぶ。比較の間は採点モデルを固定し、替えるなら別の実験とする

ループの運用から得られた教訓

 Googleは、自らの運用と他チームの観察から5つの型を挙げています。

  • 小さく代表的なデータセットから始める。1分以内で終わる4ケースなら毎回回せる。300ケースで1時間かかると、良くてリリース前の関門、悪ければ放置される
  • スコアではなく結果ファイルを保存する。前後の結果JSONがあれば、3週間後でも`eval compare`で動いたケースを特定できる
  • データセット(入力)と評価設定(期待値)を別ファイルにし、両方をバージョン管理する。スコアが動いたとき、どちらが変わったかが分かる
  • 要約指標を疑う。モデル切り替えの例のように、平均の低下が1ケースに集中していることがある
  • 評価を増やしても、修正は自動的に増えない。Googleの対照研究では、`agents-cli`を使うコーディングエージェントは評価を4倍実行した。一方で、評価後に変更する頻度は同程度だった。品質は、評価結果に基づいて行動して初めて上がる

 この対照研究はコーディングエージェントが対象で、人のチームにそのまま当てはまるとは限りません。

定期実行とスコア低下のアラート

 Agents CLIはスケジューラーを同梱していません。cronやCloud Schedulerから`eval generate`と`eval grade`を定期実行します。結果は日付ごとのフォルダーに保存します。

 安定した回帰用データセットで毎晩回すと、モデルやツールのデータ、依存関係の変化による揺らぎを捉えられます。モデル提供元の告知のない更新も検出対象です。回帰用は数十〜数百ケースが一般的です。1日1回なら、大きくても負担になりにくいからです。なお`tests/eval/datasets/regression.json`はテンプレートに含まれず、別途用意が必要です。

 結果ファイルは、誰かが見なければアラートになりません。Googleは、新しい結果の平均を基準と比べるPythonスクリプトを示しています。低下が閾値を超えると、0以外の終了コードで終わります。基準には、前回の結果か、リポジトリに保存した良好な結果を使います。閾値の既定値は0.05です。平均は、結果ファイルの`summary_metrics`先頭要素の`mean_score`から読みます。

 実例では、このスクリプトを`scripts/check_score.py`として保存しています。シェフのプロンプトの結果を閾値0.1で検査すると「FAIL: mean dropped 4.000 → 2.750」となり、終了コードは1でした。同じファイル同士なら「OK」で、終了コードは0です。cronやCloud Scheduler、GitHub Actionsは、この終了コードを受けてアラートを送れます。

プロンプトの自動最適化(eval optimize)

 ADK(Agent Development Kit)のプロジェクトでは、`eval optimize`でプロンプトを自動改善できます。内部ではGEPAフレームワークを使い、LangChain拡張には現時点で対応していません。プロンプト案を作って採点し、指標が上がった案を残す処理を繰り返します。出力はスコア順の候補で、人が確認してから反映します。

agents-cli eval optimize \

    --dataset tests/eval/datasets/regression.json \

    --target-metric final_response_quality \

    --config tests/eval/eval_config.yaml

  • 対象はプロンプトのみで、ツール・構造・モデルは固定される
  • 指標の文言に過剰適合し、点だけ上がる案も出る。その歯止めはレビュー担当者である

 この例の`–target-metric`は`final_response_quality`です。テンプレート設定の`custom_response_quality`とは名前が異なります。指標名は自分の設定と照らし合わせて指定してください。

まとめ

 Agents CLIの`eval`コマンドは、生成・採点・比較を小さく回し、劣化をケース単位で突き止める道具です。一連の実例が示すのは、平均値だけで判断しないことの大切さです。まずは数ケースの小さなデータセットで初回評価を取り、結果ファイルを残すところから始めるのが良さそうです。

この記事が気に入ったら
フォローしてね!

  • URLをコピーしました!
  • URLをコピーしました!
目次