mcpField
A
agent-eval-harness

agent-eval-harness

github.com/youdotcom-ossテスト・品質9756 回インストール今日更新
リポジトリ

agent-eval-harness について

agent-eval-harnessは、ヘッドレスCLIエージェントの実行軌跡を記録する、TypeScript/JavaScriptプロジェクト向けのコマンドラインツールです。構造化JSONLを出力し、要約、採点、調整、実行比較の評価ワークフローを備えています。

主な機能

  1. 01思考、ツール、計画の軌跡を記録
  2. 02完全な実行記録をJSONLで保存
  3. 03採点付きの複数回試行
  4. 04要約、調整、参照解答の検証
  5. 05テスト範囲の分析と実行比較

活用シーン

  1. 01エージェント動作の回帰テストを作成
  2. 02SFTまたはDPO用の学習データを生成
  3. 03モデルや設定ごとにエージェントを比較
  4. 04失敗例を確認して採点器を調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/youdotcom-oss/agent-skills --skill agent-eval-harness

インストール後、Claude Code で/agent-eval-harnessを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
docker-compose.eval.yml
Dockerfile.eval
references/
calibration.md
comparison-graders.md
docker-evals.md
eval-concepts.md
inline-graders.md
output-formats.md

詳細

エージェント評価ハーネス

目的

ヘッドレス CLI エージェントの軌跡を記録する CLI ツールです。Bun を使用する TypeScript/JavaScript プロジェクト向けに最適化されています。

ハーネスが記録し、評価はユーザーが行います。

ハーネスが提供するものユーザーが提供するもの
ヘッドレスアダプターによるプロンプトの実行スコアリングロジック(Braintrust、カスタムスクリプト)
軌跡全体の記録(思考、ツール、計画)採点器による合否判定
構造化された JSONL 出力LLM を判定者として使うプロンプト
再現可能な実行環境CI との統合、ゴールデンファイルとの比較

次の用途にお使いください:

  • 後続の評価に使用する軌跡の記録
  • 全コンテキストを含むトレーニングデータ(SFT/DPO)の生成
  • エージェントの動作に関する回帰テスト用フィクスチャの作成
  • 設定間でのエージェントの応答の比較

インストール

# Run without installing (recommended)
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json -o results.jsonl

# Or install as project dependency
bun add @plaited/agent-eval-harness

基本理念:一度記録し、さまざまな形式で利用する

flowchart LR
    Prompts["prompts.jsonl"] --> Capture["capture/trials"]
    Schema["headless schema"] --> Capture
    Capture --> Results["results.jsonl (full trajectory)"]
    Results --> Summarize["summarize"]
    Results --> Calibrate["calibrate"]
    Results --> Custom["(your tools)"]
    Summarize --> Views["summary.jsonl / .md"]
    Calibrate --> Report["calibration.md"]
    Custom --> Pipeline["any scoring platform"]

単一の出力形式: 軌跡全体を含む JSONL(常に) --format フラグなし: 専用のコマンドで形式を変換します スキーマのエクスポート: あらゆるツール向けの Zod スキーマと JSON Schema

コマンド

基本コマンド
コマンド入力出力目的
captureprompts.jsonl + schemaresults.jsonl軌跡の記録(全体)
trialsprompts.jsonl + schematrials.jsonl複数回の実行と、オプションのメトリクス
summarizeresults.jsonlsummary.jsonl or .mdコンパクトな形式への変換
calibrateresults.jsonlcalibration.mdレビュー用に失敗例を抽出
validate-refsprompts.jsonlvalidation.jsonl参照ソリューションの確認
balanceprompts.jsonlbalance.jsonテストセットのカバレッジ分析
schemas(none)JSON SchemaTypeScript 以外のユーザー向けにスキーマをエクスポート
パイプラインコマンド(Unix スタイル)
コマンド入力出力目的
runprompts.jsonl + schemaraw.jsonlプロンプトを実行し、生の出力を生成
extractraw.jsonl + schemaextracted.jsonl軌跡を解析
gradeextracted.jsonl + gradergraded.jsonl採点器によるスコアリング
formatresults.jsonljsonl/markdown/csv出力形式を変換
comparemultiple results.jsonlcomparison.json実行を比較(集計レポート)

すべてのコマンドは、スコアリング用の --grader ./grader.ts をオプションで指定できます。

Capture コマンド

基本的な使い方
bunx @plaited/agent-eval-harness capture <prompts.jsonl> --schema <schema.json> [options]
引数
引数/フラグ説明デフォルト
prompts.jsonl実行するプロンプトを含む入力ファイル必須
-s, --schemaヘッドレスアダプターのスキーマへのパス必須
-o, --output出力ファイル/パスstdout
-c, --cwdエージェントの作業ディレクトリcurrent
-t, --timeoutリクエストのタイムアウト(ミリ秒)60000
-j, --concurrency同時に実行するワーカー数1
--workspace-dirプロンプトごとにワークスペースを分離するためのベースディレクトリnone
--progress標準エラー出力に進行状況を表示false
--append出力ファイルに追記false
-g, --grader採点器モジュールへのパスnone
--debugデバッグ用に CLI の詳細な出力を表示false
例
# Basic capture
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json -o results.jsonl

# Parallel execution (4x faster with 4 workers)
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json -j 4 -o results.jsonl

# With workspace isolation for code generation tasks
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json \
  -j 4 --workspace-dir ./workspaces -o results.jsonl

# Using a local adapter script
bunx @plaited/agent-eval-harness capture prompts.jsonl bun ./my-adapter.ts -o results.jsonl

# With grader (adds score to each result)
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json --grader ./grader.ts -o results.jsonl

Trials コマンド

pass@k/pass^k 分析のために、各プロンプトを複数回実行します。

# Capture only (no grader)
bunx @plaited/agent-eval-harness trials prompts.jsonl --schema ./claude.json -k 5 -o trials.jsonl

# With grader (computes pass@k, pass^k)
bunx @plaited/agent-eval-harness trials prompts.jsonl --schema ./claude.json -k 5 --grader ./grader.ts -o trials.jsonl

# Parallel execution (4 prompts' trials run concurrently)
bunx @plaited/agent-eval-harness trials prompts.jsonl --schema ./claude.json -k 5 -j 4 -o trials.jsonl

# With workspace isolation (each trial gets its own directory)
bunx @plaited/agent-eval-harness trials prompts.jsonl --schema ./claude.json -k 5 -j 4 \
  --workspace-dir ./workspaces -o trials.jsonl

並列化に関する注意:

  • -j/--concurrency はプロンプト間で並列化します(1 つのプロンプト内の試行間では並列化しません)
  • 各プロンプトの k 回の試行は、集計に必要なため引き続き順番に実行されます
  • プロンプトが 151 件あり、-j 4 を指定すると、4 件のプロンプトの試行が同時に実行されます
  • --workspace-dir は、各試行用に {workspace-dir}/prompt-{id}-trial-{n}/ を作成します
  • 進行状況のログには、全体の完了状況が表示されます(例:12/50 prompts completed)

ワークスペースのクリーンアップ: デバッグ用に、ディレクトリは実行完了後も残ります。手動でクリーンアップしてください:

# After capture
rm -rf ./workspaces

# In CI (add as post-step)
- run: rm -rf ./workspaces
  if: always()
出力

採点器なしの場合:

{"id":"search-001","input":"Find the CEO","k":5,"trials":[{"trialNum":1,"output":"...","trajectory":[...],"duration":1234},...]}

採点器ありの場合:

{"id":"search-001","input":"Find the CEO","k":5,"passRate":0.8,"passAtK":0.99,"passExpK":0.33,"trials":[{"trialNum":1,"output":"...","pass":true,"score":1.0},...]}

Summarize コマンド

軌跡全体を含む結果から、コンパクトな形式を生成します。

# Summary JSONL (for jq analysis)
bunx @plaited/agent-eval-harness summarize results.jsonl -o summary.jsonl

# Markdown (for LLM-as-judge)
bunx @plaited/agent-eval-harness summarize results.jsonl --markdown -o results.md

Calibrate Command

採点者のレビュー用に失敗例をサンプリングします。キャリブレーションにより、エージェントの失敗(エージェントが誤った対応をした)と採点者のバグ(エージェントは正しかったが、採点者の基準が厳しすぎた)を区別できます。

# Sample failures for human review
bunx @plaited/agent-eval-harness calibrate results.jsonl --sample 10 -o calibration.md

# Re-score with different grader to compare
bunx @plaited/agent-eval-harness calibrate results.jsonl --grader ./loose-grader.ts --sample 10 -o comparison.md

キャリブレーションが重要な理由については、eval-concepts.md を参照してください。

Validate-Refs Command

エージェントを評価する前に、参照解が採点者のチェックに合格することを確認します。

# Validate reference solutions
bunx @plaited/agent-eval-harness validate-refs prompts.jsonl --grader ./grader.ts -o validation.jsonl

# Check for failures
cat validation.jsonl | jq 'select(.pass == false)'
なぜ使うのか

参照解が独自の採点者のチェックに合格しない場合:

  • タスクの定義が曖昧です
  • 採点者の基準が厳しすぎます
  • ヒントが間違っています

エージェントを評価する前に、評価設定を修正してください。

入力形式

プロンプトには reference フィールドを含める必要があります。

{"id":"test-001","input":"Create a button component","hint":"<button>","reference":"export const Button = () => <button>Click</button>"}
出力形式
{"id":"test-001","input":"Create a button component","reference":"export const Button = () => <button>Click</button>","pass":true,"score":1.0,"reasoning":"Contains hint content"}

Balance Command

テストセットの網羅性を分析し、バランスの取れた評価を実現します。

# Analyze prompt distribution
bunx @plaited/agent-eval-harness balance prompts.jsonl -o balance.json

# Pretty print
bunx @plaited/agent-eval-harness balance prompts.jsonl | jq .
なぜ使うのか

「Xを動作させる」だけの評価では、「Yを壊さない」ことを見落とします。バランス分析では、次の項目を確認できます。

  • カテゴリの分布(metadata.category に基づく)
  • 肯定例と否定例の比率
  • 網羅性の不足
出力形式
{
  "totalCases": 50,
  "categories": [
    { "name": "ui", "count": 20, "percentage": 40 },
    { "name": "logic", "count": 15, "percentage": 30 },
    { "name": "api", "count": 10, "percentage": 20 },
    { "name": "edge-case", "count": 5, "percentage": 10 }
  ],
  "underrepresented": ["edge-case"],
  "suggestions": ["Consider adding more test cases for: edge-case"]
}
バランスの取れた評価設計

肯定例と否定例の両方を含めてください。

種類例目的
肯定例「ログインボタンを追加する」エージェントが成功する必要があります
否定例「テストを壊さずにボタンを追加する」エージェントが既存の機能を壊さない必要があります
エッジケース「空の入力を適切に処理する」エージェントが堅牢である必要があります

バランスの取れたテストセットの詳細については、eval-concepts.md を参照してください。

Pipeline Workflow

パイプラインのコマンドを使うと、Unixスタイルの合成により、柔軟な評価ワークフローを構成できます。

パイプライン全体の例
# Execute → Extract → Grade → Format in one pipeline
cat prompts.jsonl | \
  bunx @plaited/agent-eval-harness run -s claude.json | \
  bunx @plaited/agent-eval-harness extract -s claude.json | \
  bunx @plaited/agent-eval-harness grade -g ./grader.ts | \
  bunx @plaited/agent-eval-harness format -f markdown > report.md
Run Command

プロンプトを実行し、生の結果を出力します。利用できるモードは3つあります。

# Schema mode (recommended)
bunx @plaited/agent-eval-harness run prompts.jsonl --schema claude.json

# Simple mode: {} placeholder substitution
bunx @plaited/agent-eval-harness run prompts.jsonl --simple "claude -p {} --output-format stream-json"

# Shell mode: $PROMPT environment variable
bunx @plaited/agent-eval-harness run prompts.jsonl --shell 'claude -p "$PROMPT" --output-format stream-json'

⚠️ セキュリティ警告: --simple モードと --shell モードでは、シェルコマンドを介してプロンプトを実行します。プロンプトはエスケープされますが、これらのモードでは信頼できないプロンプトの内容を使用しないでください。悪意のあるプロンプトテキストによって、引用符のエスケープを回避し、任意のコマンドを実行される可能性があります。信頼できない入力には、--schema モード(ヘッドレスアダプター)を使用してください。

Extract Command

生の出力を解析し、構造化された軌跡に変換します。

# From file
bunx @plaited/agent-eval-harness extract raw.jsonl --schema claude.json -o extracted.jsonl

# Piped from run
bunx @plaited/agent-eval-harness run prompts.jsonl -s claude.json | \
  bunx @plaited/agent-eval-harness extract -s claude.json
Grade Command

抽出した結果に採点者を適用します。

bunx @plaited/agent-eval-harness grade extracted.jsonl --grader ./grader.ts -o graded.jsonl
Format Command

結果を別の出力形式に変換します。

# Markdown report
bunx @plaited/agent-eval-harness format results.jsonl --style markdown -o report.md

# CSV for spreadsheets
bunx @plaited/agent-eval-harness format results.jsonl --style csv -o results.csv

# JSONL (pass-through, default)
bunx @plaited/agent-eval-harness format results.jsonl --style jsonl
Compare Command

同じプロンプトの複数の実行結果を比較します。自動検出により、CaptureResult(単一実行)形式とTrialResult(複数回実行の信頼性)形式の両方に対応します。

# Default: auto-detect format, weighted strategy, JSON output
bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl -o comparison.json

# Statistical significance strategy
bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl --strategy statistical -o comparison.json

# Custom weights via environment variables (CaptureResult)
COMPARE_QUALITY=0.7 COMPARE_LATENCY=0.2 COMPARE_RELIABILITY=0.1 \
  bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl -o comparison.json

# Markdown report format
bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl --format markdown -o report.md

# Custom grader (LLM-as-Judge)
bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl \
  --strategy custom --grader ./my-llm-judge.ts -o comparison.json

# With explicit labels
bunx @plaited/agent-eval-harness compare \
  --run "with-mcp:results-mcp.jsonl" \
  --run "vanilla:results-vanilla.jsonl" \
  -o comparison.json

Compareの使用例:

  • 同じエージェントで異なるMCPサーバーを使用する場合
  • 同じエージェントで有効にするスキルを変える場合
  • 同じエージェントでモデルのバージョンを変える場合
  • エージェント自体が異なる場合
Trials Comparison(pass@k分析)

信頼性分析のために、TrialResultファイルを比較します。

# Auto-detect trials format
bunx @plaited/agent-eval-harness compare trials1.jsonl trials2.jsonl -o comparison.json

# Explicit format (skip auto-detection)
bunx @plaited/agent-eval-harness compare trials1.jsonl trials2.jsonl --input-format trials -o comparison.json

# Custom weights for trials comparison
COMPARE_CAPABILITY=0.5 COMPARE_RELIABILITY=0.3 COMPARE_CONSISTENCY=0.2 \
  bunx @plaited/agent-eval-harness compare trials1.jsonl trials2.jsonl -o comparison.json

Trialsの指標:

指標説明計算式
能力(passAtK)K回の試行で少なくとも1回は解決できるか1 - (1-p)^k
信頼性(passExpK)毎回安定して解決できるかp^k
不安定さ能力と信頼性の差passAtK - passExpK
品質(scores)試行全体の採点者スコアの集計avg/median/p25/p75(採点者がある場合のみ)
パフォーマンス(latency)試行時間の集計p50/p90/p99/mean/min/max(常に表示)
組み込みの比較戦略

CaptureResult(単一実行)の場合:

戦略説明環境変数
weighted(デフォルト)品質、レイテンシ、信頼性COMPARE_QUALITY、COMPARE_LATENCY、COMPARE_RELIABILITY
statistical信頼区間のブートストラップCOMPARE_BOOTSTRAP_ITERATIONS
custom独自の採点器--grader path

TrialResult(複数実行)の場合:

戦略説明環境変数
weighted(デフォルト)能力、信頼性、一貫性COMPARE_CAPABILITY、COMPARE_RELIABILITY、COMPARE_CONSISTENCY
statisticalpassAtK 信頼区間のブートストラップCOMPARE_BOOTSTRAP_ITERATIONS
custom独自の採点器--grader path
比較レポートの出力

CaptureResult 形式では ComparisonReport を出力します:

{
  "meta": { "generatedAt": "...", "runs": ["baseline", "variant"], "promptCount": 100 },
  "quality": { "baseline": { "avgScore": 0.85, "passRate": 0.82 }, "variant": { ... } },
  "performance": { "baseline": { "latency": { "p50": 1200, "p90": 3400 } }, ... },
  "reliability": { "baseline": { "type": "run", "toolErrors": 5, "completionRate": 0.99 }, ... },
  "headToHead": { "pairwise": [{ "runA": "baseline", "runB": "variant", "aWins": 35, "bWins": 55 }] }
}

--strategy statistical を指定すると、品質とパフォーマンスの指標に 95% 信頼区間が含まれます:

{
  "quality": {
    "baseline": {
      "avgScore": 0.85,
      "passRate": 0.82,
      "confidenceIntervals": {
        "avgScore": [0.82, 0.88],
        "passRate": [0.79, 0.85]
      }
    }
  },
  "performance": {
    "baseline": {
      "latency": { "p50": 1200, "mean": 1350 },
      "confidenceIntervals": {
        "latencyMean": [1280, 1420]
      }
    }
  }
}

TrialResult 形式では TrialsComparisonReport を出力します:

{
  "meta": { "generatedAt": "...", "runs": ["claude", "gemini"], "promptCount": 50, "trialsPerPrompt": 5, "inputFormat": "trials" },
  "capability": { "claude": { "avgPassAtK": 0.92, "medianPassAtK": 0.95 }, "gemini": { "..." : "..." } },
  "reliability": { "claude": { "type": "trial", "avgPassExpK": 0.78, "medianPassExpK": 0.82 }, "gemini": { "..." : "..." } },
  "flakiness": { "claude": { "avgFlakiness": 0.14, "flakyPromptCount": 12 }, "gemini": { "..." : "..." } },
  "quality": { "claude": { "avgScore": 0.85, "medianScore": 0.90, "p25Score": 0.75, "p75Score": 0.95 }, "gemini": { "..." : "..." } },
  "performance": { "claude": { "latency": { "p50": 1200, "p90": 3400, "p99": 5100, "mean": 1500, "min": 800, "max": 5200 }, "totalDuration": 375000 }, "gemini": { "..." : "..." } },
  "headToHead": {
    "capability": [{ "runA": "claude", "runB": "gemini", "aWins": 28, "bWins": 18, "ties": 4 }],
    "reliability": ["..."],
    "overall": ["..."]
  }
}

注:

  • quality は採点器を使用した場合にのみ含まれます(トライアルには score フィールドがあります)
  • performance は常に含まれます(すべてのトライアルに duration があります)

--strategy statistical を指定すると、能力、信頼性、品質、パフォーマンスの指標に 95% 信頼区間が含まれます:

{
  "capability": {
    "claude": {
      "avgPassAtK": 0.92,
      "confidenceIntervals": { "avgPassAtK": [0.88, 0.95] }
    }
  },
  "reliability": {
    "claude": {
      "type": "trial",
      "avgPassExpK": 0.78,
      "confidenceIntervals": { "avgPassExpK": [0.72, 0.84] }
    }
  },
  "quality": {
    "claude": {
      "avgScore": 0.85,
      "confidenceIntervals": { "avgScore": [0.82, 0.88] }
    }
  },
  "performance": {
    "claude": {
      "latency": { "mean": 1500 },
      "confidenceIntervals": { "latencyMean": [1380, 1620] }
    }
  }
}

LLM-as-Judge パターンを含む比較採点器の詳細については、comparison-graders.md を参照してください。

比較採点器のインターフェース

CaptureResult の採点器:

import type { ComparisonGrader } from '@plaited/agent-eval-harness/pipeline'

export const grade: ComparisonGrader = async ({ id, input, hint, runs }) => {
  // runs is Record<string, { output, trajectory?, score?, duration?, toolErrors? }>
  return {
    rankings: [
      { run: 'with-mcp', rank: 1, score: 0.9 },
      { run: 'vanilla', rank: 2, score: 0.7 },
    ],
    reasoning: 'MCP run produced more accurate output'
  }
}

TrialResult の採点器:

import type { TrialsComparisonGrader } from '@plaited/agent-eval-harness/pipeline'

export const grade: TrialsComparisonGrader = async ({ id, input, hint, runs }) => {
  // runs is Record<string, { passAtK?, passExpK?, k, trials }>
  // Each trial in trials has: { duration, score?, pass?, output, trajectory }
  return {
    rankings: [
      { run: 'claude', rank: 1, score: 0.92 },
      { run: 'gemini', rank: 2, score: 0.85 },
    ],
    reasoning: 'Claude has higher reliability with lower flakiness'
  }
}
パイプラインのワークフロー図
flowchart LR
    Prompts["prompts.jsonl"] --> Run["run"]
    Schema["headless schema"] --> Run
    Run --> Raw["raw.jsonl"]
    Raw --> Extract["extract"]
    Schema --> Extract
    Extract --> Extracted["extracted.jsonl"]
    Extracted --> Grade["grade"]
    Grader["grader.ts"] --> Grade
    Grade --> Graded["graded.jsonl"]
    Graded --> Format["format"]
    Format --> Output["report.md / .csv / .jsonl"]

    Graded --> Compare["compare"]
    Results2["other runs..."] --> Compare
    CompareGrader["compare-grader.ts"] --> Compare
    Compare --> Comparison["comparison.jsonl"]

Schemas コマンド

TypeScript 以外のツール用に JSON スキーマをエクスポートします。

# List available schemas
bunx @plaited/agent-eval-harness schemas

# Export all schemas as JSON
bunx @plaited/agent-eval-harness schemas --json -o schemas.json

# Export specific schema
bunx @plaited/agent-eval-harness schemas CaptureResult --json
bunx @plaited/agent-eval-harness schemas TrialResult --json
bunx @plaited/agent-eval-harness schemas GraderResult --json
利用可能なスキーマ
スキーマ説明
CaptureResult単一キャプチャの出力(id、input、output、trajectory、timing)
TrialResult複数実行トライアルの出力(passAtK、passExpK を含む)
GraderResult採点器の戻り値(pass、score、reasoning)
PromptInput入力プロンプトの形式
TrajectorySteptrajectory 配列内の単一ステップ
SummaryResultコンパクトな要約形式
他の言語での使用

Python、Go などでの検証用にスキーマをエクスポートします:

# Export all schemas
bunx @plaited/agent-eval-harness schemas --json -o schemas.json

# Use in Python with jsonschema
python -c "
import json
from jsonschema import validate

with open('schemas.json') as f:
    schemas = json.load(f)

with open('results.jsonl') as f:
    for line in f:
        result = json.loads(line)
        validate(result, schemas['CaptureResult'])
        print(f'{result[\"id\"]}: valid')
"

採点器のインターフェース

採点器は、キャプチャした軌跡に対して意味的な合否スコアを付けます。このハーネスは、任意の言語で記述された採点器をサポートします。

Git ベースの採点(コーディングタスクに推奨)

パスではなく、結果を採点します。 オプションの cwd パラメーターを使用して、git で環境の変更を検出します:

// git-grader.ts
import type { Grader } from '@plaited/agent-eval-harness/schemas'

export const grade: Grader = async ({ output, hint, cwd }) => {
  if (!cwd) return { pass: false, score: 0, reasoning: 'No cwd' }
  
  // Detect file changes
  const status = await Bun.$`git -C ${cwd} status --porcelain`.text()
  const filesCreated = status
    .split('\n')
    .filter(line => line.startsWith('??'))
    .map(line => line.slice(3).trim())
  
  // Verify tests pass
  const testResult = await Bun.$`cd ${cwd} && bun test`.nothrow()
  
  return {
    pass: filesCreated.length > 0 && testResult.exitCode === 0,
    score: testResult.exitCode === 0 ? 1 : 0,
    reasoning: `Files: ${filesCreated.join(', ')}. Tests: ${testResult.exitCode === 0 ? 'pass' : 'fail'}`,
    outcome: {  // Optional: structured data for analysis
      filesCreated,
      testsPassed: testResult.exitCode === 0,
      type: 'file_creation_with_tests'
    }
  }
}

git ベースの結果採点パターンの詳細については、inline-graders.md を参照してください。

出力ベースの採点(汎用)
// my-grader.ts
import type { Grader } from '@plaited/agent-eval-harness/schemas'

export const grade: Grader = async ({ input, output, hint, trajectory }) => {
  const pass = output.toLowerCase().includes(hint?.toLowerCase() ?? '')
  return {
    pass,
    score: pass ? 1 : 0,
    reasoning: pass ? 'Contains hint content' : 'Missing hint content'
  }
}

注: input は string(単一ターン)または string[](複数ターン)を指定できます。hint フィールドは採点器にコンテキストを提供します(expected から名称が変更されました)。

Python/実行可能ファイルの採点器

stdin/stdout の JSON プロトコルを使用することで、任意の実行可能ファイルを採点器として使用できます:

#!/usr/bin/env python3
import json, sys

data = json.load(sys.stdin)
output = data.get("output", "").lower()
hint = (data.get("hint") or "").lower()

pass_result = hint in output if hint else True
print(json.dumps({
    "pass": pass_result,
    "score": 1.0 if pass_result else 0.0,
    "reasoning": "Contains hint" if pass_result else "Missing hint"
}))
chmod +x ./grader.py
bunx @plaited/agent-eval-harness capture prompts.jsonl --schema ./claude.json --grader ./grader.py -o results.jsonl

LLM-as-Judge パターンを含む採点器の詳細については、inline-graders.md を参照してください。

入力形式

prompts.jsonl の各行:

{"id":"test-001","input":"Create a button","hint":"should contain <button>"}
{"id":"test-002","input":["Create a button","Make it blue"],"metadata":{"category":"ui"}}
フィールド必須説明
idはい一意の識別子
inputはい単一のプロンプト(string)または会話ターン(string[])
hintいいえ採点器のコンテキスト — 確認すべき内容(厳密な一致ではありません)
referenceいいえ参照ソリューション(validate-refs 用)
metadataいいえフィルタリング用のタグ、カテゴリ、難易度
timeoutいいえこのプロンプトのデフォルトタイムアウトを上書きします

セッションの動作: JSONL の各エントリーは、新しいセッション 1 つに対応します

  • input: string → セッション 1 つ、プロンプト 1 つ
  • input: string[] → セッション 1 つ、プロンプト N 個(順次ターン)

出力形式

完全な軌跡の JSONL(常時):

{
  "id": "test-001",
  "input": "Find the CEO of Anthropic",
  "output": "The CEO of Anthropic is Dario Amodei.",
  "hint": "should mention Dario Amodei",
  "trajectory": [
    {"type": "thought", "content": "I'll search for this...", "timestamp": 100},
    {"type": "tool_call", "name": "WebSearch", "status": "completed", "input": {...}, "output": {...}, "duration": 500},
    {"type": "message", "content": "The CEO of Anthropic is Dario Amodei.", "timestamp": 700}
  ],
  "metadata": {
    "category": "search",
    "agent": "--schema ./claude.json",
    "trajectoryRichness": "full",
    "turnCount": 1
  },
  "timing": {
    "start": 1704067200000,
    "end": 1704067201234,
    "firstResponse": 100,
    "sessionCreation": 234,
    "total": 1234,
    "inputTokens": 150,
    "outputTokens": 85
  },
  "toolErrors": false
}
出力フィールド
フィールド説明
input元のプロンプト(文字列、または複数ターンの場合は string[])
hint採点者向けのコンテキストヒント(提供されている場合)
metadata.trajectoryRichness"full" | "messages-only" | "minimal"
metadata.turnCount会話ターン数(文字列の場合は 1、配列の場合は N)
timing.sessionCreationセッション作成にかかった時間(ms)
timing.total合計所要時間(終了 - 開始)
timing.inputTokens消費した入力トークン数(アダプターから取得できる場合)
timing.outputTokens生成した出力トークン数(アダプターから取得できる場合)
toolErrorsツール呼び出しに失敗があったかどうか

注: toolErrors は、誤解を招く status: 'passed'|'failed' に代わるものです。実際の合否は、あなたの採点者によって判定されます。

スキーマのエクスポート

利用側では、Zod スキーマを直接インポートできます。

import { CaptureResultSchema, TrialResultSchema } from '@plaited/agent-eval-harness/schemas'

// Validate external data
const result = CaptureResultSchema.parse(jsonData)

// Generate JSON Schema (Zod 4 native)
import * as z from 'zod'
const jsonSchema = z.toJSONSchema(CaptureResultSchema)
信頼性メトリクスの判別可能なユニオン

信頼性メトリクスには、型安全な解析のために type 判別子が含まれます。

import * as z from 'zod'
import {
  ReliabilityMetricsSchema,       // type: 'run'
  TrialsReliabilityMetricsSchema  // type: 'trial'
} from '@plaited/agent-eval-harness/schemas'

// Create a unified schema for both metric types
const UnifiedReliabilitySchema = z.discriminatedUnion('type', [
  ReliabilityMetricsSchema,
  TrialsReliabilityMetricsSchema,
])

// Type-safe parsing with automatic narrowing
const metrics = UnifiedReliabilitySchema.parse(data)
if (metrics.type === 'run') {
  // TypeScript knows: ReliabilityMetrics
  console.log(metrics.toolErrors, metrics.completionRate)
} else {
  // TypeScript knows: TrialsReliabilityMetrics
  console.log(metrics.avgPassExpK, metrics.medianPassExpK)
}

TypeScript 以外のツールでは、JSON スキーマをエクスポートできます。

bunx @plaited/agent-eval-harness schemas --json -o schemas.json
bunx @plaited/agent-eval-harness schemas CaptureResult --json

実行環境

推奨: 一貫性のある隔離された実行環境を確保するため、ハーネスは Docker コンテナ内で実行してください。

# Run integration tests via Docker
docker compose -f docker-compose.test.yml run --rm test

# Or with explicit API keys
ANTHROPIC_API_KEY=sk-... GEMINI_API_KEY=... docker compose -f docker-compose.test.yml run --rm test
Docker の要件
要件理由
Node.js 24+Gemini CLI は最新の JS 機能(オプショナルチェーン)を使用します
非 root ユーザーClaude CLI は root による --dangerously-skip-permissions をブロックします
Gemini API キーGemini CLI 用に GEMINI_API_KEY を渡します

Docker の完全なセットアップガイド、デバッグのヒント、CI 統合パターンについては、docker-evals.md を参照してください。

複数ターンの会話

input: string[] を使用すると、1 つのセッション内で複数ターンの会話を実行できます。

{"id":"context-001","input":["Remember this number: 42","What number did I ask you to remember?"],"hint":"42"}
{"id":"context-002","input":["My name is Alice","What is my name?"],"hint":"Alice"}

ヘッドレスアダプターを使って実行します。

# Using Claude Code via headless adapter
bunx @plaited/agent-eval-harness capture multi-turn.jsonl \
  bunx @plaited/agent-eval-harness headless --schema ./claude-headless.json \
  -o results.jsonl

# Using Gemini CLI via headless adapter
GEMINI_API_KEY=... bunx @plaited/agent-eval-harness capture multi-turn.jsonl \
  bunx @plaited/agent-eval-harness headless --schema ./gemini-headless.json \
  -o results.jsonl

要点:

  • 各 JSONL エントリーは、新しいセッション 1 つに対応します
  • input: string[] は、同じセッションに順番にターンを送信します
  • stream モード(Claude)と iterative モード(Gemini)の両方で動作します
  • アダプターがコンテキストの保持を自動的に処理します

下流での統合

ハーネスは、あらゆるツールにパイプできる標準的な JSONL を出力します。

# Filter with jq
cat results.jsonl | jq 'select(.metadata.category == "ui")'

# Count tool usage
cat results.jsonl | jq -s 'map(.trajectory | map(select(.type == "tool_call")) | length) | add'

# Summarize for quick analysis
bunx @plaited/agent-eval-harness summarize results.jsonl -o summary.jsonl

# Compare runs with built-in strategies
bunx @plaited/agent-eval-harness compare run1.jsonl run2.jsonl -o comparison.json

クイックリファレンス

リソース説明
bunx @plaited/agent-eval-harnessCLI ヘルプ
output-formats.mdJSONL スキーマ、コマンドの詳細
inline-graders.md単一の入力/出力を対象とする採点器(TypeScript、Python、shell)
comparison-graders.md比較戦略(重み付け、統計的手法、LLM-as-Judge)
calibration.md採点器のキャリブレーションワークフロー
eval-concepts.md評価の概念(pass@k、pass^k)
docker-evals.mdDocker のセットアップ、デバッグ、CI 統合

関連項目

コメント