AI Agent Cost Analysis and Performance Benchmarking: A Complete Framework
The bojieli/ai-agent-book repository provides a reusable framework that unifies financial cost tracking and performance metrics through normalized usage payloads, statistical summarization, and rigorous gate checks.
Effective AI Agent cost analysis and performance benchmarking requires more than simple logging. The ai-agent-book repository demonstrates how to build a systematic evaluation pipeline that tracks every token, millisecond, and dollar across experimental arms while maintaining statistical rigor.
Unified Cost Tracking Architecture
The framework centers on a normalized cost payload that standardizes LLM usage data across different providers. Every LLM call returns a usage dictionary containing fields like tokens, prompt_tokens, completion_tokens, time_ms, storage_bytes, and optionally a provider-reported cost.
In chapter8/self-modifying-agent/llm_generator.py (lines 106‑121), the system extracts and normalizes this data:
# Normalization logic from llm_generator.py
cost = usage.get("cost")
provider_reported_cost_usd = float(cost) if cost is not None else None
normalized_cost = {
"tokens": usage.get("tokens", 0),
"prompt_tokens": usage.get("prompt_tokens", 0),
"completion_tokens": usage.get("completion_tokens", 0),
"time_ms": usage.get("time_ms", 0),
"storage_bytes": usage.get("storage_bytes", 0),
"provider_reported_cost_usd": provider_reported_cost_usd,
}
This flat structure ensures that downstream analysis can aggregate costs across different models and providers without vendor-specific parsing logic.
Metric Abstraction and Statistical Summarization
Rather than hardcoding metric extraction, the framework uses a lambda-based metric map defined in chapter8/self-evolution-eval/run_experiment_8_6.py (lines 23‑36):
METRICS = {
"learning_accuracy": lambda r: r["phase_accuracy"]["learning"],
"transfer_accuracy": lambda r: r["phase_accuracy"]["transfer"],
"tokens": lambda r: float(r["cost"]["tokens"]),
"prompt_tokens": lambda r: float(r["cost"]["prompt_tokens"]),
"completion_tokens": lambda r: float(r["cost"]["completion_tokens"]),
"latency_ms": lambda r: float(r["cost"]["time_ms"]),
"provider_reported_cost_usd": lambda r: r["cost"].get("provider_reported_cost_usd"),
}
The describe function (lines 43‑55) computes statistical summaries for any metric list, returning n, mean, sample standard deviation, and a 95% confidence interval using the t-distribution:
def describe(values: list[float]) -> dict:
import statistics, math
n = len(values)
mean = statistics.mean(values) if values else 0.0
stdev = statistics.stdev(values) if n > 1 else 0.0
margin = (1.96 * stdev / math.sqrt(n)) if n > 1 else 0.0
return {
"n": n,
"mean": round(mean, 6),
"sample_stdev": round(stdev, 6),
"ci95_t": [round(mean - margin, 6), round(mean + margin, 6)],
}
Cost Capture Flow Implementation
The system implements a four-stage pipeline for reliable cost analysis:
- LLM Request Wrapping – Agents like
OpenAILongitudinalAgentcapture raw provider responses - Normalization –
llm_generator.pyextracts cost data and storesprovider_reported_cost_usdorNonewhen unavailable - Aggregation –
chapter8/trajectory-verifier/evidence_client.py(lines 71‑83) sums costs across multiple calls:
# From evidence_client.py
native_cost = sum(obs["cost"] for obs in cost_observations)
summary = {
"provider_reported_cost_usd": round(native_cost, 9) if cost_observations else None,
"cost_qualification": (
"provider-native usage.cost summed across all calls"
if cost_observations
else "provider did not expose monetary cost; no price was guessed"
),
}
- Run-Level Consolidation – Experiment scripts attach the cost dict to run reports, enabling global summaries across all seeds and arms
Performance Benchmarking Methodology
For performance benchmarking, the framework supports multi-arm experiments with statistical comparison. After defining the METRICS dictionary, the system:
- Aggregates by arm: Groups runs by experimental condition (e.g., "static", "append_only", "evolving")
- Computes summaries: Applies
describeto each metric within each arm - Calculates paired differences: Compares metrics across arms using matched seeds for statistical power
From run_experiment_8_6.py (lines 18‑24), the paired difference logic:
# Compare evolving vs static arms using same seeds
paired[comparison] = {
name: describe([
METRICS[name](indexed[(left, seed)]) - METRICS[name](indexed[(right, seed)])
for seed in seeds
])
for name in METRICS
}
Gate Checks for Data Integrity
Before trusting any metrics, the system validates experimental integrity through gate checks (lines 42‑53):
gates = {
"three_real_model_arms_completed": all(
len(by_arm[arm]) == len(seeds) for arm in ARMS
),
"current_answer_never_leaked_before_action": all(
_no_answer_leak(receipt) for receipt in receipts
),
"all_response_ids_unique": len(set(r["response_id"] for r in runs)) == len(runs),
}
These assertions ensure that cost and performance numbers are trustworthy before reporting.
Practical Implementation Examples
Copy these patterns to implement AI Agent cost analysis in your own benchmarks:
1. Normalize any provider usage dict:
def normalise_cost(usage: dict) -> dict:
native = float(usage.get("cost", 0.0))
return {
"tokens": usage.get("tokens", 0),
"prompt_tokens": usage.get("prompt_tokens", 0),
"completion_tokens": usage.get("completion_tokens", 0),
"time_ms": usage.get("time_ms", 0),
"storage_bytes": usage.get("storage_bytes", 0),
"provider_reported_cost_usd": native if native else None,
"cost_qualification": (
"provider-native usage.cost" if native
else "provider did not expose monetary cost; no price was guessed"
),
}
2. Define experiment metrics:
METRICS = {
"accuracy": lambda r: r["accuracy"],
"tokens": lambda r: float(r["cost"]["tokens"]),
"latency": lambda r: float(r["cost"]["time_ms"]),
"cost_usd": lambda r: r["cost"].get("provider_reported_cost_usd"),
}
3. Summarize experimental arms:
runs = [...] # List of run reports
by_arm = {
arm: [r for r in runs if r["arm"] == arm]
for arm in ("baseline", "optimized")
}
summaries = {
arm: {
name: describe([METRICS[name](run) for run in arm_runs])
for name in METRICS
}
for arm, arm_runs in by_arm.items()
}
Summary
- Normalize usage payloads across providers using a flat cost structure that captures tokens, latency, storage, and monetary cost
- Abstract metrics through lambda mappings to enable clean statistical aggregation without hardcoded extraction logic
- Apply rigorous statistics using the
describefunction for means, standard deviations, and 95% confidence intervals - Validate with gate checks to ensure experimental integrity before reporting cost or performance numbers
- Use paired differences when comparing agent variants to maintain statistical power across experimental arms
Frequently Asked Questions
How does the framework handle providers that don't expose monetary costs?
When a provider does not return a cost field in the usage payload, the system stores provider_reported_cost_usd as None and sets cost_qualification to indicate that no price was guessed. This prevents synthetic cost estimates from contaminating financial analysis while still tracking token counts and latency for performance comparisons.
What statistical measures are used for comparing agent performance?
The framework computes n (sample size), mean, sample standard deviation, and 95% confidence intervals using the t-distribution. For comparing experimental arms, it calculates paired differences by matching runs with the same seed across conditions, then applies the same statistical summarization to the differences. This approach controls for seed-specific variance and provides robust statistical testing.
How are gate checks implemented to ensure data integrity?
Gate checks are boolean assertions defined in a dictionary that verify experimental invariants before analysis. According to chapter8/self-evolution-eval/run_experiment_8_6.py, these include verifying that all arms completed the required number of seeds, ensuring no answer leakage occurred during the experiment, and confirming that all response IDs are unique. If any gate fails, the experiment reports the failure rather than unreliable metrics.
Can this framework benchmark multiple agent variants simultaneously?
Yes. The architecture supports multi-arm experiments where each arm (e.g., "static", "append_only", "evolving") runs across multiple random seeds. The system aggregates metrics per arm, computes statistical summaries for each, and performs pairwise comparisons between arms using matched seeds. This design enables simultaneous performance benchmarking of different agent architectures or prompt strategies under identical conditions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →