agent-eval-harness について
agent-eval-harnessは、ヘッドレスCLIエージェントの実行軌跡を記録する、TypeScript/JavaScriptプロジェクト向けのコマンドラインツールです。構造化JSONLを出力し、要約、採点、調整、実行比較の評価ワークフローを備えています。
主な機能
- 01思考、ツール、計画の軌跡を記録
- 02完全な実行記録をJSONLで保存
- 03採点付きの複数回試行
- 04要約、調整、参照解答の検証
- 05テスト範囲の分析と実行比較
活用シーン
- 01エージェント動作の回帰テストを作成
- 02SFTまたはDPO用の学習データを生成
- 03モデルや設定ごとにエージェントを比較
- 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.ymlDockerfile.evalreferences/calibration.mdcomparison-graders.mddocker-evals.mdeval-concepts.mdinline-graders.mdoutput-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
コマンド
基本コマンド
| コマンド | 入力 | 出力 | 目的 |
|---|---|---|---|
capture | prompts.jsonl + schema | results.jsonl | 軌跡の記録(全体) |
trials | prompts.jsonl + schema | trials.jsonl | 複数回の実行と、オプションのメトリクス |
summarize | results.jsonl | summary.jsonl or .md | コンパクトな形式への変換 |
calibrate | results.jsonl | calibration.md | レビュー用に失敗例を抽出 |
validate-refs | prompts.jsonl | validation.jsonl | 参照ソリューションの確認 |
balance | prompts.jsonl | balance.json | テストセットのカバレッジ分析 |
schemas | (none) | JSON Schema | TypeScript 以外のユーザー向けにスキーマをエクスポート |
パイプラインコマンド(Unix スタイル)
| コマンド | 入力 | 出力 | 目的 |
|---|---|---|---|
run | prompts.jsonl + schema | raw.jsonl | プロンプトを実行し、生の出力を生成 |
extract | raw.jsonl + schema | extracted.jsonl | 軌跡を解析 |
grade | extracted.jsonl + grader | graded.jsonl | 採点器によるスコアリング |
format | results.jsonl | jsonl/markdown/csv | 出力形式を変換 |
compare | multiple results.jsonl | comparison.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 |
statistical | passAtK 信頼区間のブートストラップ | 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 | 入力プロンプトの形式 |
TrajectoryStep | trajectory 配列内の単一ステップ |
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-harness | CLI ヘルプ |
| output-formats.md | JSONL スキーマ、コマンドの詳細 |
| inline-graders.md | 単一の入力/出力を対象とする採点器(TypeScript、Python、shell) |
| comparison-graders.md | 比較戦略(重み付け、統計的手法、LLM-as-Judge) |
| calibration.md | 採点器のキャリブレーションワークフロー |
| eval-concepts.md | 評価の概念(pass@k、pass^k) |
| docker-evals.md | Docker のセットアップ、デバッグ、CI 統合 |
関連項目
- headless-adapters skill - ヘッドレス CLI エージェント向けのスキーマ駆動型アダプター