TL;DR
- prompt / skill / tool 権限の変更は、Agent の behavior の変更です。コードの回帰テストや文言チェックでは止まりません。
- このリポジトリの静的ガード
check_risk_gate_drift.pyで試しました(社内データ、ref 434fb628、2026-09-25)。fail-safe の文言を消す変更は exit 1 で止まり、文言を残して例外を足す変更は exit 0 で通りました。 - 守るには、変更前後の Agent に同じ入力を通す eval dataset と、致命ケース / 平均スコア / 回帰差分 / cost / latency に分けた失敗条件が要ります。
- eval ジョブは
.agents/skillsなどの paths で絞って走らせます。ただし skipped は required status check を通過するので、対象パスの漏れは検査漏れになります。 - このリポジトリでは behavior eval をまだ回していません。測っていない数値は書かず、出す数値は外部出典か
擬似例のラベルを付けます。
はじめに
対象は、prompt や skill、Agent の tool 権限を PR で変えている AI Engineer・Platform・Tech Lead です。読み終えると、ケースの書式、失敗条件の表、CI の置き場所を自分のリポジトリに持ち込めます。
Anthropic は Agent の eval について「pre-launch と CI/CD で、Agent の変更とモデル更新のたびに回す自動 eval が品質問題に対する最初の防衛線」と書いています(Demystifying evals for AI agents)。本記事はこの考え方を、1 つのリポジトリの実測から具体化します。
1. 何を評価するのか
既存記事との違いは評価対象です。本記事の対象は、openai/evals が扱う「LLM と LLM を使ったシステム」の評価のうち、Agent の判断にあたります。
| 記事 | 評価対象 | 止めたい変化 |
|---|---|---|
| AI生成PRの品質ゲート | AI が書いたコード | バグ・規約違反 |
| AI回帰テスト | コードの振る舞い | 既存機能の回帰 |
| LLM出力の品質ゲート | LLM アプリの出力 | 出力品質の劣化 |
| Harnessの技術的負債 | Harness の量と到達性 | 死んだガードの滞留 |
| 本記事 | Agent 自身の判断 | prompt・skill 変更による判断の変化 |
このリポジトリの .agents/skills/ は 90 ディレクトリ(git ls-tree -d HEAD .agents/skills/ | wc -l)あり、git log --since=2026-06-25 -- .agents/skills は 44 コミットでした(社内データ、ref 434fb628)。3 か月で 44 回、Agent の behavior を変えうる変更が入っています。
2. 自リポの静的ガードで before/after を測る
check_risk_gate_drift.py は、正本(spec/article_risk_gate.md)と転記先の文面から意味を抽出して一致を見る静的ガードです。pnpm test から呼ばれます。記事の risk 判定について「判定不能なら medium にフォールバックする」という fail-safe の文言を見ています。
リポジトリのコピーに 2 種類の変更を加えて測りました。コマンドの sed -i '' は macOS(BSD)の書式です。GNU sed では sed -i にしてください。
W=$(mktemp -d)
mkdir -p "$W/.claude" && cp -R spec .agents "$W/" && cp -R .claude/commands "$W/.claude/"
python3 scripts/check_risk_gate_drift.py --repo-root "$W"; echo "exit=$?"
# 変更A: fail-safe の文言を消す
sed -i '' 's/判定不能は `M5` として `medium` にフォールバックし、/判定不能は `M5` として `low` に丸め、/' "$W/.agents/skills/article-preflight/SKILL.md"
python3 scripts/check_risk_gate_drift.py --repo-root "$W"; echo "exit=$?"
# 変更B: 文言を残したまま例外を足す
sed -i '' 's/判定不能は `M5` として `low` に丸め、/判定不能は `M5` として `medium` にフォールバックし(ただし締切が近い記事は low としてよい)、/' "$W/.agents/skills/article-preflight/SKILL.md"
python3 scripts/check_risk_gate_drift.py --repo-root "$W"; echo "exit=$?"
コピー先には git がないため、実行のたびに WARNING: git が使えないため R-4 走査を作業ツリーへ degrade しました が出ます。今回の判定対象は fail-safe 文言の有無なので、結果には影響しません。
| 条件 | 出力の要点 | exit(社内データ) |
|---|---|---|
| 原文 | risk gate drift check passed. | 0 |
| 変更A(文言削除) | fail-safe の記述が見つからない旨の ERROR | 1 |
| 変更B(例外追加) | risk gate drift check passed. | 0 |
変更B は「判定不能なら medium」を残したまま、締切が近ければ low にしてよい例外を足しています。Agent の判断は緩みますが、検査は通ります。
Harnessの技術的負債 の節5では、ガードは「止めるべきものを止め、通すべきものを通す」二面で検証すべきだと書きました。このガードは二面を満たしています。それでも、意味を変える変更は通ります。文面の検査の限界であり、その先は behavior を直接見るしかありません。
3. eval dataset の作り方
LangSmith は dataset を「アプリケーションの評価に使う example の集まり」と定義しています(Evaluation concepts)。Agent 設定の eval では、example の単位を 「変更で壊れうる判断」 に置きます。1 ケースは「入力 + 期待する判断 + 採点方法」の 3 点です。
# 擬似例: article-preflight の risk 判定ケース
- id: risk-unknown-near-deadline
input: "締切が明日の記事。一次ソースの有無が判定できない"
expected: { risk_level: medium }
grader: exact_match # code-based
critical: true # 1 件でも落ちたら fail
- id: risk-cited-howto
input: "公式ドキュメントのみを根拠にした手順記事"
expected: { risk_level: low }
grader: exact_match
critical: false
1 つ目のケースは、変更B の例外をそのまま突く入力です。静的ガードが通した変更を、behavior の側で落とします。
採点は自動化できる形に寄せます。Claude のドキュメントは、問いを選択式・文字列一致・コード採点・LLM 採点のように自動採点できる形へ構造化することを勧めています(Define success criteria and build evaluations)。Anthropic の記事も grader を code-based・model-based・human の 3 種に分けています。
ケースの出どころは、過去の障害とレビューで差し戻した判断です。件数やゴールデンセットの育て方は LLM出力の品質ゲート に任せます。
4. score threshold と CI 失敗条件
Agent 設定の変更に特有なのは、変更前(main)と変更後(PR)に同じケースを通して比べる点です。単独のスコアではなく差分で判定します。
| 失敗条件 | 判定 | 狙い |
|---|---|---|
| 致命ケース | critical: true が 1 件でも不合格なら fail | fail-safe の破壊を平均で埋もれさせない |
| 平均スコア | 合格率がしきい値未満なら fail | 全体の劣化 |
| 回帰差分 | main で合格・PR で不合格のケースがあれば fail か要レビュー | 変更起因の劣化だけを拾う |
| cost / latency | 上限超過で fail(節5) | 品質以外の劣化 |
平均スコアのしきい値は、promptfoo の CI 連携例では合格率 95% 未満で exit 1 にしています(ドキュメントの例示値。CI/CD integration)。同ページでは promptfoo eval --fail-on-error でテスト失敗時に落とし、合格率は -o results.json の出力を jq で集計します。専用のしきい値キーはこのページには見当たりません。
LLM の出力は非決定的です。設計の軸は 2 つです。同じケースを複数回回して合格率で見ること、main と PR を同じケース・同じ回数で比べること。回数の数値は自リポにも外部出典にも根拠がないため、ここでは出しません。
5. cost / latency gate
prompt が長くなる変更や、tool 呼び出しが増える変更は、品質が保たれたまま遅く高くなることがあります。Claude のドキュメントも成功基準の例に Latency と Price を挙げています。
promptfoo には assertion type として latency(ミリ秒の上限)と cost があり、上限は threshold で書きます(Expected outputs)。cost は cost 情報を持つモデルでしか働きません。
# 擬似例: 上限値は自リポで測っていない
defaultTest:
assert:
- type: latency
threshold: 20000
- type: cost
threshold: 0.05
上限値は main の実測から決め、PR で大きく超えたら fail にするのが筋です。上の数値は書式を示すための 擬似例 です。
6. CI のどこに置くか
eval は API コストがかかるため、Agent 設定が変わる PR だけで走らせます。
# 擬似例: .github/workflows/agent-eval.yml
on:
pull_request:
paths:
- ".agents/skills/**"
- ".agents/agents/**"
- ".claude/commands/**"
- "AGENTS.md"
ここに落とし穴があります。GitHub の保護ブランチでは、required status check は successful・skipped・neutral のいずれかで通過します(About protected branches)。paths で外れてスキップされた eval ジョブは merge を止めません。tool 権限の設定ファイルなど、behavior を変えるパスを列挙し漏らすと、そのまま素通しになります。権限側の設計は Agentの影響範囲設計 も参照してください。
7. このリポジトリで測れていないこと
- behavior eval は回していません。eval dataset は 0 件です。
skill-optimizerのeval-rubric-template.mdには 5 基準(Trigger quality / Gate quality / Task fidelity / Verification quality / Output contract compliance)の rubric テンプレートがあります。埋まった実例と CI 実行はありません。spec/article_retrospective_loop.mdは、skill 指示の変更を baseline・採用しきい値・却下しきい値・試行回数を含む eval plan で評価すると定めています。運用実績はまだありません。- GitHub Actions は billing 問題で止まっています。ワークフローに書いてあっても実行されていません。裏付けはローカルの
pnpm testだけです。
つまり本記事で実測したのは「静的ガードの穴」までです。eval の効果は測っていません。
まとめ
Agent 設定の変更は、文言を残したまま意味を変えられます。静的ガードは必要ですが、それだけでは止まりません。次の順で始めてください。
- 自分のリポジトリの静的ガードに、節2 のような「文言を残して例外を足す」変更を当てて、通るかを確かめる
- 通った変更を突くケースを
critical: trueで 1 件書く - main と PR で同じケースを回し、節4 の表の失敗条件を CI に入れる
- paths の対象に tool 権限の設定が入っているか確認する
FAQ
静的ガードがあれば eval は要りませんか
要ります。節2 のとおり、文言削除は exit 1 で止まり、例外の追加は exit 0 で通りました。文面の検査は意味の変化を見ません。
eval dataset は何件あればよいですか
この記事では件数を出しません。自リポに根拠がないためです。件数の考え方は LLM出力の品質ゲート を参照してください。
paths フィルタで eval ジョブを絞ると何が起きますか
skipped は required status check を通過します。対象パスの漏れはそのまま検査漏れになります。
このリポジトリでは behavior eval を回していますか
回していません。dataset は 0 件で、CI も止まっています。本記事の設計は、測った穴に対する提案です。
References
- Anthropic, Demystifying evals for AI agents(確認日 2026-09-25)
- Claude Docs, Define success criteria and build evaluations(確認日 2026-09-25)
- LangSmith, Evaluation concepts(確認日 2026-09-25)
- promptfoo, CI/CD integration(確認日 2026-09-25)
- promptfoo, Expected outputs (assertions)(確認日 2026-09-25)
- GitHub Docs, About protected branches(確認日 2026-09-25)
- OpenAI, openai/evals(確認日 2026-09-25)
