Agent Evaluation Framework Builder — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Agent Evaluation Framework Builder (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill designs an evaluation framework for an LLM agent or pipeline. Most teams skip evals until something breaks in production — this skill helps you build evals before launch so you have a baseline, catch regressions, and measure quality improvements objectively. It covers dataset construction, metric selection, LLM-as-judge setup, and CI integration.
Copy this file to .agents/skills/agent-eval-framework-builder/SKILL.md in your project root.
Then ask:
Provide:
Describe the agent and its task alongside these instructions.
When asked to build an evaluation framework, produce the following:
| Agent Task | Eval Type | Reason |
|---|---|---|
| Factual Q&A with known answers | Exact match / F1 | Ground truth available |
| Summarization, drafting | LLM-as-judge | No single right answer |
| Code generation | Unit test execution | Correctness is verifiable |
| Multi-step agent task | Trajectory scoring | Need to evaluate the path, not just the endpoint |
| Classification / routing | Accuracy, F1 | Categorical output |
| RAG retrieval | Recall@K, MRR | Measure retrieval quality separately |
Use multiple eval types for complex agents: trajectory scoring + LLM-as-judge output quality.
Minimum viable eval dataset: 50 examples covering:
Generating eval data when you don't have ground truth:
# Use a stronger model to generate expected outputs
def generate_ground_truth(inputs: list[str], system_prompt: str) -> list[dict]:
results = []
for inp in inputs:
response = strong_model.invoke([
SystemMessage(content=system_prompt),
HumanMessage(content=inp)
])
results.append({"input": inp, "expected": response.content})
return resultsHave a human review at least 20% of generated ground truth before using it.
For open-ended outputs (summaries, drafts, agent responses):
JUDGE_PROMPT = """You are evaluating an AI assistant's response.
Task: {task_description}
Input: {input}
Expected behavior: {criteria}
Actual response: {actual_response}
Score the response on each dimension (1-5):
- Correctness: Does it answer the question accurately?
- Completeness: Does it cover all required aspects?
- Conciseness: Is it appropriately brief without omitting key information?
- Safety: Does it avoid harmful, biased, or inappropriate content?
Respond in JSON: {{"correctness": N, "completeness": N, "conciseness": N, "safety": N, "overall": N, "reasoning": "..."}}"""
def llm_judge(input: str, actual: str, criteria: str) -> dict:
response = judge_model.invoke(JUDGE_PROMPT.format(
task_description=TASK_DESCRIPTION,
input=input,
criteria=criteria,
actual_response=actual
))
return json.loads(response.content)LLM-as-judge best practices:
For multi-step agents, evaluate the path taken, not just the final answer:
def evaluate_trajectory(expected_steps: list[str], actual_steps: list[str]) -> dict:
"""Compare the agent's action sequence to the expected sequence."""
# Check if required steps are present (order-agnostic)
required_present = all(step in actual_steps for step in expected_steps)
# Check for unnecessary detours
extra_steps = [s for s in actual_steps if s not in expected_steps]
efficiency = len(expected_steps) / max(len(actual_steps), 1)
return {
"required_steps_completed": required_present,
"efficiency_score": efficiency,
"unnecessary_steps": extra_steps
}Key trajectory metrics:
import json
from dataclasses import dataclass
@dataclass
class EvalResult:
input: str
expected: str
actual: str
scores: dict
passed: bool
def run_eval_suite(agent, dataset: list[dict], threshold: float = 3.5) -> dict:
results = []
for case in dataset:
actual = agent.invoke(case["input"])
scores = llm_judge(case["input"], actual, case.get("criteria", ""))
passed = scores["overall"] >= threshold
results.append(EvalResult(
input=case["input"],
expected=case.get("expected", ""),
actual=actual,
scores=scores,
passed=passed
))
pass_rate = sum(r.passed for r in results) / len(results)
avg_score = sum(r.scores["overall"] for r in results) / len(results)
return {
"pass_rate": pass_rate,
"average_score": avg_score,
"total": len(results),
"passed": sum(r.passed for r in results),
"results": results
}Add eval runs to your CI pipeline to catch regressions:
# .github/workflows/eval.yml
name: Agent Evals
on:
pull_request:
paths: ['prompts/**', 'agents/**']
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run eval suite
run: python run_evals.py
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Check pass rate
run: |
PASS_RATE=$(cat eval_results.json | jq '.pass_rate')
if (( $(echo "$PASS_RATE < 0.85" | bc -l) )); then
echo "Eval pass rate $PASS_RATE below threshold 0.85"
exit 1
fiGate merges on: pass rate ≥ 85% and no regression on existing test cases.
| Metric | What it measures | Target |
|---|---|---|
| Pass rate | % cases meeting quality threshold | ≥ 85% |
| Average judge score | Mean quality across all cases | ≥ 3.8/5 |
| Regression rate | % previously-passing cases now failing | 0% |
| Tool accuracy | % correct tool selections by agent | ≥ 90% |
| Latency p95 | 95th percentile response time | < 8s |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.