サンタメソッド は何をしますか?
マルチエージェント対抗検証フレームワーク。リストを作り、2度確認しよう。悪い子なら、良い子になるまで修正する。
核となる洞察: 1つのエージェントが自身の出力をレビューしても、出力を生成したときと同じバイアス、知識のギャップ、系統的なエラーを共有している。2人の独立したレビュアーがコンテキストを共有せずにレビューすることで、この障害モードを打破する。
いつ起動するか
以下の場合にこのスキルを呼び出してください:
- 出力が公開、デプロイ、またはエンドユーザーによって消費される場合
- コンプライアンス、規制、またはブランドの制約を順守する必要がある場合
- 人間のレビューなしでコードが本番環境に出荷される場合
- コンテンツの正確性が重要な場合(技術文書、教育資料、顧客向けコピー)
- 大規模なバッチ生成で、スポットチェックでは系統的なパターンを見逃す場合
- ハルシネーションのリスクが高い場合(主張、統計、APIリファレンス、法的表現)
内部ドラフト、探索的リサーチ、または決定論的な検証が可能なタスク(これらにはビルド・テスト・リンターパイプラインを使用)には使用しないでください。
アーキテクチャ
┌─────────────┐
│ 生成エージェント │ フェーズ1: リストを作る
│ (Agent A) │ 成果物を生成する
└──────┬───────┘
│ 出力
▼
┌──────────────────────────────┐
│ 二重独立レビュー │ フェーズ2: 2度確認する
│ │
│ ┌───────────┐ ┌───────────┐ │ 2つのエージェント、同じルーブリック
│ │ レビュアーB │ │ レビュアーC │ │ コンテキスト非共有
│ └─────┬─────┘ └─────┬─────┘ │
│ │ │ │
└────────┼──────────────┼────────┘
│ │
▼ ▼
┌──────────────────────────────┐
│ 評決ゲート │ フェーズ3: 良い子か悪い子か
│ │
│ B合格 かつ C合格 → 良い子 │ 両方合格必須。
│ それ以外 → 悪い子 │ 例外なし。
└──────┬──────────────┬─────────┘
│ │
良い子 悪い子
│ │
▼ ▼
[ 出荷 ] ┌─────────────┐
│ 修正サイクル │ フェーズ4: 良い子になるまで修正
│ │
│ iteration++ │ すべてのフラグを収集。
│ i > MAX の場合:│ すべての問題を修正。
│ エスカレーション│ 両方のレビュアーを再実行。
│ それ以外: │ 収束するまでループ。
│ goto フェーズ2│
└──────────────┘
フェーズ詳細
フェーズ1: リストを作る(生成)
プライマリタスクを実行します。通常の生成ワークフローに変更はありません。サンタメソッドは生成後の検証レイヤーであり、生成戦略ではありません。
# ジェネレータは通常通り実行
output = generate(task_spec)
フェーズ2: 2度確認する(独立二重レビュー)
2つのレビューエージェントを並行して起動します。重要な不変条件:
- コンテキスト分離 — どちらのレビュアーも相手の評価を見ない
- 同一ルーブリック — 両方に同じ評価基準が与えられる
- 同一入力 — 両方とも元の仕様と生成された出力を受け取る
- 構造化出力 — 各レビュアーは散文ではなく型付き評決を返す
REVIEWER_PROMPT = """
あなたは独立した品質レビュアーです。この出力に対する他のレビューは一切見ていません。
## タスク仕様
{task_spec}
## レビュー対象の出力
{output}
## 評価ルーブリック
{rubric}
## 指示
評価ルーブリックの各基準に対して出力を評価してください。それぞれについて:
- PASS: 基準を完全に満たしており、問題なし
- FAIL: 特定の問題を発見(問題の正確な内容を引用)
評価を構造化JSONとして返却:
{
"verdict": "PASS" | "FAIL",
"checks": [
{"criterion": "...", "result": "PASS|FAIL", "detail": "..."}
],
"critical_issues": ["..."], // 修正必須のブロッカー
"suggestions": ["..."] // ブロックしない改善提案
}
厳密に行ってください。あなたの仕事は問題を見つけることであり、承認することではありません。
"""
# レビュアーを並行して起動(Claude Codeサブエージェント)
review_b = Agent(prompt=REVIEWER_PROMPT.format(...), description="サンタレビュアーB")
review_c = Agent(prompt=REVIEWER_PROMPT.format(...), description="サンタレビュアーC")
# 両方が同時に実行 — お互いは見えない
ルーブリック設計
ルーブリックは最も重要な入力です。曖昧なルーブリックは曖昧なレビューを生みます。すべての基準に客観的な合格/不合格条件が必要です。
| 基準 | 合格条件 | 不合格シグナル |
|---|---|---|
| 事実の正確性 | すべての主張がソース資料または一般常識に対して検証可能 | 捏造された統計、間違ったバージョン番号、存在しないAPI |
| ハルシネーションなし | 捏造されたエンティティ、引用、URL、参照がない | 存在しないページへのリンク、出典のない引用 |
| 完全性 | 仕様のすべての要件が対応されている | セクション欠落、エッジケースのスキップ、不完全なカバレッジ |
| コンプライアンス | すべてのプロジェクト固有の制約をパス | 禁止用語の使用、トーンの違反、規制不適合 |
| 内部一貫性 | 出力内に矛盾がない | セクションAでXと言っているのにセクションBでnot-Xと言っている |
| 技術的正確性 | コードがコンパイル/実行される、アルゴリズムが正しい | 構文エラー、ロジックバグ、誤った複雑性の主張 |
ドメイン固有ルーブリック拡張
コンテンツ/マーケティング:
- ブランドボイスの順守
- SEO要件の充足(キーワード密度、メタタグ、構造)
- 競合他社の商標の不正使用がない
- CTAが存在し、正しくリンクされている
コード:
- 型安全性(
anyのリークなし、適切なnull処理) - エラーハンドリングのカバレッジ
- セキュリティ(コード内にシークレットなし、入力検証、インジェクション防止)
- 新規パスのテストカバレッジ
コンプライアンス重要(規制、法律、金融):
- 成果保証や実証されていない主張がない
- 必要な免責事項が存在する
- 承認された用語のみ使用
- 管轄区域に適した言語
フェーズ3: 良い子か悪い子か(評決ゲート)
def santa_verdict(review_b, review_c):
"""両方のレビュアーが合格する必要があります。部分点はありません。"""
if review_b.verdict == "PASS" and review_c.verdict == "PASS":
return "NICE" # 出荷
# 両方のレビュアーからのフラグをマージ、重複排除
all_issues = dedupe(review_b.critical_issues + review_c.critical_issues)
all_suggestions = dedupe(review_b.suggestions + review_c.suggestions)
return "NAUGHTY", all_issues, all_suggestions
なぜ両方とも合格しなければならないのか: 片方のレビュアーだけが問題をキャッチした場合でも、その問題は現実のものです。もう片方のレビュアーの盲点こそ、サンタメソッドが排除しようとしている障害モードです。
フェーズ4: 良い子になるまで修正(収束ループ)
MAX_ITERATIONS = 3
for iteration in range(MAX_ITERATIONS):
verdict, issues, suggestions = santa_verdict(review_b, review_c)
if verdict == "NICE":
log_santa_result(output, iteration, "passed")
return ship(output)
# すべての重大な問題を修正(提案は任意)
output = fix_agent.execute(
output=output,
issues=issues,
instruction="フラグが立った問題のみを修正してください。リファクタリングやリクエストされていない変更を追加しないでください。"
)
# 修正された出力で両方のレビュアーを再実行(新しいエージェント、前回のラウンドの記憶なし)
review_b = Agent(prompt=REVIEWER_PROMPT.format(output=output, ...))
review_c = Agent(prompt=REVIEWER_PROMPT.format(output=output, ...))
# 反復回数を使い果たした — エスカレーション
log_santa_result(output, MAX_ITERATIONS, "escalated")
escalate_to_human(output, issues)
重要: 各レビューラウンドでは新しいエージェントを使用します。レビュアーは前のラウンドからの記憶を引き継いではいけません。以前のコンテキストはアンカリングバイアスを生み出すからです。
実装パターン
パターンA: Claude Codeサブエージェント(推奨)
サブエージェントは真のコンテキスト分離を提供します。各レビュアーは共有状態のない独立したプロセスです。
# Claude Codeセッション内で、Agentツールを使用してレビュアーを起動
# 両方のエージェントを並行して実行することで高速化
# Agentツール呼び出しの疑似コード
reviewer_b = Agent(
description="サンタレビューB",
prompt=f"品質についてこの出力をレビューしてください...\n\nルーブリック:\n{rubric}\n\n出力:\n{output}"
)
reviewer_c = Agent(
description="サンタレビューC",
prompt=f"品質についてこの出力をレビューしてください...\n\nルーブリック:\n{rubric}\n\n出力:\n{output}"
)
パターンB: シーケンシャルインライン(フォールバック)
サブエージェントが利用できない場合、明示的なコンテキストリセットで分離をシミュレート:
- 出力を生成
- 新しいコンテキスト: 「あなたはレビュアー1です。このルーブリックに対してのみ評価してください。問題を見つけてください。」
- 結果をそのまま記録
- コンテキストを完全にクリア
- 新しいコンテキスト: 「あなたはレビュアー2です。このルーブリックに対してのみ評価してください。問題を見つけてください。」
- 両方のレビューを比較し、修正し、繰り返す
サブエージェントパターンが明らかに優れています — インラインシミュレーションはレビュアー間のコンテキスト漏洩のリスクがあります。
パターンC: バッチサンプリング
大規模バッチ(100+アイテム)の場合、全アイテムに完全なサンタを実行するのはコストがかかりすぎます。層化サンプリングを使用:
- ランダムサンプル(バッチの10〜15%、最低5アイテム)でサンタを実行
- 失敗をタイプ別に分類(ハルシネーション、コンプライアンス、完全性など)
- 系統的なパターンが見つかった場合、バッチ全体に対象を絞った修正を適用
- 修正されたバッチを再度サンプリングして再検証
- クリーンなサンプルが合格するまで継続
import random
def santa_batch(items, rubric, sample_rate=0.15):
sample = random.sample(items, max(5, int(len(items) * sample_rate)))
for item in sample:
result = santa_full(item, rubric)
if result.verdict == "NAUGHTY":
pattern = classify_failure(result.issues)
items = batch_fix(items, pattern) # パターンに一致するすべてのアイテムを修正
return santa_batch(items, rubric) # 再サンプリング
return items # クリーンなサンプル → バッチ出荷
障害モードと緩和策
| 障害モード | 症状 | 緩和策 |
|---|---|---|
| 無限ループ | 修正後もレビュアーが新しい問題を発見し続ける | 最大反復回数キャップ(3回)。エスカレーション。 |
| ゴム印承認 | 両方のレビュアーがすべてを合格させる | 対抗プロンプト: 「あなたの仕事は問題を見つけることであり、承認することではありません。」 |
| 主観的ドリフト | レビュアーがエラーではなくスタイルの好みをフラグする | 客観的な合格/不合格基準のみの厳格なルーブリック |
| 修正の回帰 | 問題Aを修正すると問題Bが発生する | 各ラウンドで新しいレビュアーが回帰をキャッチ |
| レビュアー一致バイアス | 両方のレビュアーが同じものを見逃す | 独立性によって緩和されるが、排除はされない。重要な出力の場合は、3人目のレビュアーまたは人間によるスポットチェックを追加。 |
| コスト爆発 | 大規模出力で反復回数が多すぎる | バッチサンプリングパターン。検証サイクルごとの予算上限。 |
他のスキルとの統合
| スキル | 関係 |
|---|---|
| 検証ループ | 決定論的チェック(ビルド、リンター、テスト)に使用。サンタは意味論的チェック(正確性、ハルシネーション)に使用。最初に検証ループ、次にサンタを実行。 |
| Evalハーネス | サンタメソッドの結果が評価指標を提供。Santa実行全体でのpass@kを追跡し、生成品質の経時変化を測定。 |
| 継続的学習v2 | サンタの発見がインスティンクトになる。同じ基準での繰り返しの失敗 → そのパターンを避けるための学習された振る舞い。 |
| 戦略的コンパクト | コンパクト化の前にサンタを実行。検証の途中でレビューコンテキストを失わないようにする。 |
メトリクス
サンタメソッドの有効性を測定するためにこれらを追跡:
- 初回合格率: ラウンド1でサンタに合格する出力の割合(目標: >70%)
- 収束までの平均反復回数: NICEまでの平均ラウンド数(目標: <1.5)
- 問題の分類: 失敗タイプの分布(ハルシネーション vs 完全性 vs コンプライアンス)
- レビュアー一致率: 両方のレビュアーによってフラグされた問題の割合 vs 片方のみ(一致率が低い = ルーブリックの調整が必要)
- エスケープ率: 出荷後に発見された、サンタがキャッチすべきだった問題(目標: 0)
コスト分析
サンタメソッドのコストは、検証サイクルごとに生成単独のトークンコストの約2〜3倍です。ほとんどの高リスク出力にとって、これはお買い得です:
サンタのコスト = (生成トークン) + 2×(ラウンドあたりのレビュートークン) × (平均ラウンド数)
サンタなしのコスト = (評判の低下) + (修正の労力) + (信頼の喪失)
バッチ運用の場合、サンプリングパターンによりコストを完全検証の約15〜20%に抑えながら、系統的な問題の90%以上をキャッチできます。