mcpField
A
agent-eval-harness

agent-eval-harness

github.com/youdotcom-oss测试与质量9756 次安装今天更新
代码仓库

关于 agent-eval-harness

agent-eval-harness 是面向 TypeScript/JavaScript 项目的命令行工具,用于捕获无头 CLI Agent 的执行轨迹。它输出结构化 JSONL,并提供汇总、评分、校准和运行对比等评估工作流。

主要功能

  1. 01捕获 Agent 思路、工具和计划轨迹
  2. 02以 JSONL 保存完整执行记录
  3. 03支持多次试运行与评分
  4. 04汇总、校准和验证参考答案
  5. 05分析测试集覆盖并比较运行结果

适用场景

  1. 01为 Agent 行为构建回归测试
  2. 02生成 SFT 或 DPO 训练数据
  3. 03比较不同模型或配置的 Agent
  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

详细介绍

Agent Eval Harness

用途

用于从无头 CLI Agent 捕获执行轨迹的命令行工具,针对使用 Bun 的 TypeScript/JavaScript 项目进行了优化。

Harness 负责捕获。评分由你完成。

Harness 提供你提供
通过无头适配器执行提示词评分逻辑(Braintrust、自定义脚本)
完整捕获执行轨迹(思考、工具、计划)通过评分器判定通过/失败
结构化 JSONL 输出LLM-as-judge 提示词
可复现的执行环境CI 集成、黄金文件比较

适用于以下场景:

  • 为下游评估捕获执行轨迹
  • 在完整上下文中生成训练数据(SFT/DPO)
  • 为 Agent 行为构建回归测试夹具
  • 比较不同配置下的 Agent 响应

安装

# 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 标志:**通过单独的命令派生视图 **Schema 导出:**提供 Zod Schema + JSON Schema,适用于各种工具

命令

核心命令
命令输入输出用途
captureprompts.jsonl + schemaresults.jsonl捕获执行轨迹(完整)
trialsprompts.jsonl + schematrials.jsonl多次运行 + 可选指标
summarizeresults.jsonlsummary.jsonl 或 .md派生精简视图
calibrateresults.jsonlcalibration.md抽取失败样本供审查
validate-refsprompts.jsonlvalidation.jsonl检查参考解答
balanceprompts.jsonlbalance.json分析测试集覆盖情况
schemas(无)JSON Schema为非 TS 用户导出 Schema
管道命令(Unix 风格)
命令输入输出用途
runprompts.jsonl + schemaraw.jsonl执行提示词,输出原始结果
extractraw.jsonl + schemaextracted.jsonl解析执行轨迹
gradeextracted.jsonl + gradergraded.jsonl应用评分器评分
formatresults.jsonljsonl/markdown/csv转换输出格式
compare多个 results.jsonlcomparison.json比较运行结果(汇总报告)

所有命令都支持使用可选参数 --grader ./grader.ts 进行评分。

Capture 命令

基本用法
bunx @plaited/agent-eval-harness capture <prompts.jsonl> --schema <schema.json> [options]
参数
参数/标志描述默认值
prompts.jsonl包含待执行提示词的输入文件必填
-s, --schema无头适配器 Schema 的路径必填
-o, --output输出文件/路径stdout
-c, --cwdAgent 的工作目录当前目录
-t, --timeout请求超时时间,单位为 ms60000
-j, --concurrency并发工作进程数1
--workspace-dir用于隔离每个提示词工作区的基目录无
--progress在 stderr 中显示进度false
--append追加到输出文件false
-g, --grader评分器模块的路径无
--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 会在不同提示词之间并行执行(不会并行执行同一提示词的多次试验)
  • 每个提示词的 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 命令

抽样检查失败案例,供评分器审核。校准有助于区分Agent 失败(Agent 做错了)和评分器错误(Agent 是正确的,但评分器过于严格)。

# 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 命令

在评估 Agent 之前,检查参考解决方案是否能通过你的评分器。

# 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)'
为什么要使用?

如果参考解决方案未能通过你自己的评分器:

  • 任务定义含糊不清
  • 评分器过于严格
  • 提示有误

请先修复评估,再评估 Agent。

输入格式

提示词必须包含 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 命令

分析测试集覆盖范围,确保评估均衡。

# 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"]
}
均衡的评估设计

同时包含正向和负向案例:

类型示例目的
正向“添加一个登录按钮”Agent 应该成功
负向“添加一个按钮,同时不破坏测试”Agent 不应该破坏现有功能
边缘案例“妥善处理空输入”Agent 应该具备鲁棒性

如需进一步了解均衡测试集,请参阅 eval-concepts.md。

Pipeline 工作流

Pipeline 命令支持 Unix 风格的组合方式,让评估工作流更加灵活。

完整 Pipeline 示例
# 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 命令

执行提示词并输出原始结果。提供三种模式:

# 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 模式会通过 Shell 命令执行提示词。虽然提示词会经过转义,但在这些模式下不要使用不可信的提示词内容。恶意提示词文本可能绕过引号转义并执行任意命令。对于不可信的输入,请使用 --schema 模式(无头适配器)。

Extract 命令

将原始输出解析为结构化轨迹:

# 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 命令

对提取的结果应用评分器:

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

将结果转换为不同的输出格式:

# 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 命令

比较同一组提示词的多次运行。支持 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 的使用场景:

  • 同一 Agent 使用不同的 MCP 服务
  • 同一 Agent 启用不同的技能
  • 同一 Agent 使用不同版本的模型
  • 完全不同的 Agent
Trials 比较(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-p)^k
可靠性(passExpK)每次都能稳定成功p^k
不稳定性能力与可靠性之间的差距passAtK - passExpK
质量(分数)汇总各次试验的评分器分数avg/median/p25/p75(仅在使用评分器时提供)
性能(延迟)汇总各次试验的持续时间p50/p90/p99/mean/min/max(始终提供)
内置比较策略

对于 CaptureResult(单次运行):

策略描述环境变量
weighted(默认)质量、延迟、可靠性COMPARE_QUALITY、COMPARE_LATENCY、COMPARE_RELIABILITY
statistical使用 Bootstrap 计算置信区间COMPARE_BOOTSTRAP_ITERATIONS
custom自定义评分器--grader path

对于 TrialResult(多次运行):

策略描述环境变量
weighted(默认)能力、可靠性、一致性COMPARE_CAPABILITY、COMPARE_RELIABILITY、COMPARE_CONSISTENCY
statistical使用 Bootstrap 计算 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 schemas。

# 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
可用的 Schema
Schema描述
CaptureResult单次捕获输出(id、input、output、trajectory、timing)
TrialResult多次运行试验输出(包含 passAtK、passExpK)
GraderResult评分器返回值(pass、score、reasoning)
PromptInput输入提示词格式
TrajectorySteptrajectory 数组中的单个步骤
SummaryResult紧凑摘要格式
在其他语言中的用法

导出 schema,以便在 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消耗的输入 token 数(如果适配器提供)
timing.outputTokens生成的输出 token 数(如果适配器提供)
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-evals.md,了解完整的 Docker 设置指南、调试技巧和 CI 集成模式。

多轮对话

使用 input: string[] 在单个会话中执行多轮对话:

{"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 记录 = 一个全新的会话
  • 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 评审)
calibration.md评分器校准工作流
eval-concepts.md评估概念(pass@k、pass^k)
docker-evals.mdDocker 设置、调试、CI 集成

相关内容

评论

支持 Markdown