Most AI agents are evaluated on benchmarks that don’t predict real-world performance. SWE-bench scores don’t tell you if an agent will loop infinitely on your codebase. Terminal-Bench doesn’t measure cost efficiency.
Here’s how to evaluate agent reliability with metrics that actually matter.
The evaluation problem
AI agents fail in ways that traditional software doesn’t:
- Inconsistency: Same input, different output each run
- Hallucination: Confidently wrong answers
- Infinite loops: Agent keeps trying the same failing approach
- Cost explosion: Simple task burns $50 in API calls
- Silent failure: Agent reports success but output is wrong
Traditional testing (assert expected output) doesn’t work because agent outputs are non-deterministic. You need probabilistic evaluation.
Metrics that matter
1. Task success rate
The most important metric. What percentage of tasks does the agent complete correctly?
def evaluate_success_rate(agent, test_cases, runs_per_case=5):
results = []
for case in test_cases:
successes = 0
for _ in range(runs_per_case):
result = agent.run(case.input)
if is_correct(result, case.expected):
successes += 1
results.append(successes / runs_per_case)
return sum(results) / len(results)
Run each test case multiple times (5-10) to account for non-determinism. A 90% success rate means the agent fails 1 in 10 times on average.
2. Consistency
How much does the agent’s output vary across runs?
def evaluate_consistency(agent, test_case, runs=10):
outputs = [agent.run(test_case.input) for _ in range(runs)]
unique_outputs = len(set(str(o) for o in outputs))
return 1 - (unique_outputs - 1) / (runs - 1) # 1 = identical, 0 = all different
High consistency (0.8+) means the agent is reliable. Low consistency (0.3-) means outputs are random.
3. Cost efficiency
How much does each successful task cost?
def evaluate_cost_efficiency(agent, test_cases, runs_per_case=5):
costs = []
for case in test_cases:
for _ in range(runs_per_case):
result, cost = agent.run_with_cost(case.input)
if is_correct(result, case.expected):
costs.append(cost)
return {
'median_cost': median(costs),
'p95_cost': percentile(costs, 95),
'mean_cost': mean(costs),
}
Track median and p95 cost. A median of $0.10 with p95 of $2.00 means occasional expensive runs.
4. Time to completion
How long does each task take?
def evaluate_latency(agent, test_cases, runs_per_case=3):
times = []
for case in test_cases:
for _ in range(runs_per_case):
start = time.time()
agent.run(case.input)
times.append(time.time() - start)
return {
'median_seconds': median(times),
'p95_seconds': percentile(times, 95),
}
5. Error rate and recovery
How often does the agent fail, and does it recover gracefully?
def evaluate_error_handling(agent, test_cases):
errors = []
for case in test_cases:
try:
result = agent.run(case.input)
if not is_correct(result, case.expected):
errors.append({'type': 'wrong_output', 'case': case})
except Exception as e:
errors.append({'type': 'exception', 'error': str(e), 'case': case})
return {
'error_rate': len(errors) / len(test_cases),
'error_types': Counter(e['type'] for e in errors),
}
6. Safety metrics
Does the agent produce harmful, biased, or dangerous outputs?
def evaluate_safety(agent, test_cases):
unsafe = []
for case in test_cases:
result = agent.run(case.input)
if contains_pii(result):
unsafe.append({'type': 'pii_leak', 'case': case})
if contains_harmful_content(result):
unsafe.append({'type': 'harmful', 'case': case})
if ignores_safety_instructions(result, case.safety_rules):
unsafe.append({'type': 'rule_violation', 'case': case})
return {
'unsafe_rate': len(unsafe) / len(test_cases),
'violation_types': Counter(u['type'] for u in unsafe),
}
Building a test suite
Task categories
Your test suite should cover:
- Simple tasks: Agent should succeed 95%+ of the time
- Medium tasks: Agent should succeed 80%+ of the time
- Hard tasks: Agent should succeed 50%+ of the time
- Edge cases: Agent should fail gracefully (not crash)
- Adversarial inputs: Agent should not be tricked
Test case structure
@dataclass
class AgentTestCase:
input: str
expected: Any # Expected output or success criteria
category: str # 'simple', 'medium', 'hard', 'edge', 'adversarial'
max_cost: float # Maximum acceptable cost
max_time: float # Maximum acceptable time in seconds
safety_rules: list[str] # Safety constraints
Example test suite
test_suite = [
AgentTestCase(
input="Fix the bug in auth.py where login fails on empty password",
expected="auth.py modified with null check",
category="simple",
max_cost=0.50,
max_time=60,
safety_rules=["no credentials in output", "no file deletion"],
),
AgentTestCase(
input="Refactor the payment module to support multiple currencies",
expected="payment module refactored with currency abstraction",
category="medium",
max_cost=5.00,
max_time=300,
safety_rules=["no direct database modifications", "no test deletion"],
),
AgentTestCase(
input="Optimize the database query that's causing 500ms latency",
expected="query optimized, latency under 100ms",
category="hard",
max_cost=10.00,
max_time=600,
safety_rules=["no schema changes without approval", "no data deletion"],
),
]
Running evaluations
Manual evaluation
For subjective tasks (code quality, writing quality), use human evaluation:
def human_evaluate(agent_output, criteria):
"""Have a human rate the output on specified criteria."""
scores = {}
for criterion in criteria:
score = input(f"Rate {criterion} (1-5): ")
scores[criterion] = int(score)
return scores
Automated evaluation
For objective tasks (pass/fail, measurable improvements), use automated evaluation:
def automated_evaluate(agent_output, test_case):
"""Automatically evaluate agent output."""
if test_case.category == 'code_fix':
return run_tests(agent_output) # Does the code pass tests?
elif test_case.category == 'performance':
return measure_latency(agent_output) < test_case.max_time
else:
return compare_output(agent_output, test_case.expected)
LLM-as-judge
Use a stronger model to evaluate the agent’s output:
def llm_judge(agent_output, criteria):
"""Use a strong model to evaluate output quality."""
judge_prompt = f"""
Evaluate this output based on: {criteria}
Output: {agent_output}
Score 1-5 and explain why.
"""
return call_strong_model(judge_prompt)
Evaluation frequency
| Stage | Frequency | What to evaluate |
|---|---|---|
| Development | Every code change | Success rate, consistency |
| Pre-deployment | Before each release | Full test suite |
| Production | Daily/weekly | Success rate, cost, latency |
| Post-incident | After every failure | Root cause, safety |
My take
Most teams evaluate agents on benchmarks that don’t predict real-world performance. SWE-bench doesn’t tell you if the agent will loop infinitely on your codebase.
Focus on three metrics:
- Task success rate (run each test 5+ times)
- Cost per successful task (median and p95)
- Consistency (how much output varies across runs)
Build a test suite with simple, medium, and hard tasks. Run it before every deployment. Track metrics over time.
The goal is not “does the agent score well on benchmarks?” The goal is “does the agent reliably complete real tasks at acceptable cost?”
FAQ
How many times should I run each test?
5-10 times per test case. AI agents are non-deterministic, so a single run doesn’t tell you reliability. Run multiple times and calculate success rate.
What’s a good success rate?
For simple tasks: 95%+. For medium tasks: 80%+. For hard tasks: 50%+. Below these thresholds, the agent needs improvement before production use.
How do I evaluate subjective tasks?
Use LLM-as-judge (have a strong model evaluate outputs) or human evaluation. Combine both for the best results.
How do I detect infinite loops?
Set maximum step counts and time limits. If the agent exceeds either, terminate and mark as failure. Track loop frequency as a metric.
Should I evaluate in production?
Yes. Track success rate, cost, and latency in production. Use sampling (evaluate 10% of tasks) to keep costs manageable.
Related Articles
- Best AI Agent Observability Platforms
- AI Agent Logging and Tracing
- AI Agent Error Handling
- Deploy AI Agents Production
- AI Agent Security