How to Analyze and Optimize Agent API Costs: A Complete Guide to Token Tracking

The most effective way to analyze and optimize agent API costs is to implement automatic token tracking using the TokenCost service, which wraps LLM calls to record usage, calculates real-time costs using LiteLLM pricing data, and provides actionable summaries to identify expensive models and limit runaway spending.

The browser-use-rpa chapter in the bojieli/ai-agent-book repository provides a production-ready solution for analyzing and optimizing agent API costs through its lightweight cost-tracking subsystem. This system automatically measures LLM token consumption and converts those counts into precise monetary costs, giving you full visibility into where your budget is being spent.

Understanding the TokenCost Architecture

The cost-tracking functionality centers around the TokenCost class in browser_use/tokens/service.py, which orchestrates pricing data loading, LLM call wrapping, and usage aggregation. Supporting Pydantic models in browser_use/tokens/views.py define the data structures for pricing information, individual usage entries, and aggregated summaries.

Core Components and Data Models

The system relies on several key classes defined in browser_use/tokens/views.py:

  • TokenCostCalculated – Stores computed costs including prompt costs, cached read costs, cache creation costs, and completion costs.
  • ModelPricing – Holds per-token pricing for input, output, cache reads, and cache creation (particularly relevant for Anthropic models).
  • TokenUsageEntry – Records a single LLM invocation with model name, timestamp, and token counts.
  • UsageSummary – Aggregates total tokens, total cost, and per-model statistics across all recorded usage.

Pricing Data Management

The service fetches pricing data from the LiteLLM repository's model_prices_and_context_window.json file. This data is cached in the XDG cache directory at ~/.cache/browser_use/token_cost with timestamped files and a default 24-hour cache duration.

When TokenCost.initialize() is called, the system executes _load_pricing_data(), which invokes _find_valid_cache() to locate recent cached data. If no valid cache exists within the 24-hour window, _fetch_and_cache_pricing_data() pulls fresh data using httpx, stores it in a timestamped file (e.g., pricing_YYYYMMDD_HHMMSS.json), and prunes old caches automatically.

Implementing Cost Tracking in Your Agent

To begin analyzing API costs, you must instantiate the TokenCost service and register your LLM instances. This process is controlled by the BROWSER_USE_CALCULATE_COST environment variable or the explicit include_cost parameter.

Enabling the TokenCost Service

Cost tracking is disabled by default to minimize overhead. Enable it by setting the environment variable or passing the flag directly:

from browser_use.tokens.service import TokenCost

# Option 1: Environment variable

import os
os.environ["BROWSER_USE_CALCULATE_COST"] = "true"

# Option 2: Explicit flag

cost_service = TokenCost(include_cost=True)

The TokenCost.__init__ method reads this configuration to determine whether to perform monetary calculations and sets up internal storage for usage history and registered LLM instances.

Registering LLM Instances

Once the service is initialized, wrap your LLM using the register_llm method. This stores the original LLM's ainvoke coroutine and replaces it with a wrapper that automatically records token usage:

from browser_use.llm.base import BaseChatModel

# Initialize your LLM (e.g., OpenAIChat, AnthropicChat)

my_llm: BaseChatModel = ...

# Register with cost tracking

cost_service.register_llm(my_llm)

The wrapper guarantees zero-impact on LLM functionality while asynchronously logging usage via add_usage and firing background tasks to write human-readable logs via _log_usage.

Analyzing Usage and Costs

After your agent completes its tasks, retrieve detailed breakdowns of token consumption and associated costs to identify optimization opportunities.

Retrieving Usage Summaries

Call get_usage_summary to aggregate all recorded entries into a comprehensive report:


# After agent execution

summary = await cost_service.get_usage_summary()

print(f"Total tokens: {summary.total_tokens}")
print(f"Total cost: ${summary.total_cost:.4f}")

# Per-model breakdown

for model_name, stats in summary.by_model.items():
    print(f"{model_name}: {stats.total_tokens} tokens → ${stats.cost:.4f}")

This method processes the in-memory list of TokenUsageEntry objects, optionally calculating costs on-the-fly using the loaded pricing data, and returns a UsageSummary containing total tokens, total cost, and per-model statistics.

Interpreting Cost Breakdowns

The calculate_cost method (called internally by the tracking system) computes four distinct cost components:

  1. New prompt cost – Uncached prompt tokens × input_cost_per_token
  2. Cached read cost – Cached prompt tokens × cache_read_input_token_cost
  3. Cache creation cost – Tokens used to create caches × cache_creation_input_token_cost
  4. Completion cost – Output tokens × output_cost_per_token

Monitor the per-model breakdown to identify expensive models (e.g., GPT-4) that might be candidates for replacement with cheaper alternatives where quality requirements permit.

Optimization Strategies for Production

Implement these practical techniques to keep agent API bills under control while maintaining performance.

Limiting Agent Steps to Prevent Runaway Costs

Configure a hard ceiling on the number of LLM invocations to prevent infinite loops from consuming unlimited tokens:


# In your agent configuration (see examples/01_basic_task.py)

config = {
    "max_agent_steps": 10,  # Stop after 10 LLM calls

}

As shown in examples/01_basic_task.py, this parameter ensures deterministic cost boundaries during both development and production runs.

Leveraging Prompt Caching

Use LLMs that support prompt caching (such as Anthropic models) and monitor the cached-token breakdown (indicated by 💾 in logs). The TokenCost service tracks cache_read_input_token_cost separately from standard input costs, typically resulting in significant savings for repeated prompts.

Managing Pricing Data Freshness

Keep calculations accurate and storage minimal with these maintenance operations:


# Keep only the 2 most recent cache files

await cost_service.clean_old_caches(keep_count=2)

# Force refresh pricing data after model announcements

await cost_service.refresh_pricing_data()

The clean_old_caches method removes all but the specified number of recent cache files (default is 3), while refresh_pricing_data bypasses the cache to fetch current market rates from the LiteLLM repository.

Summary

  • Enable cost tracking only during profiling by setting BROWSER_USE_CALCULATE_COST=true or passing include_cost=True to TokenCost.
  • Register LLMs with cost_service.register_llm(my_llm) to automatically wrap all invocations with zero performance impact.
  • Analyze spending by calling await cost_service.get_usage_summary() to review total costs and per-model breakdowns.
  • Prevent runaway costs by configuring max_agent_steps limits in your agent configuration.
  • Optimize with caching by using models that support prompt caching and monitoring cached read percentages.
  • Maintain freshness by periodically running clean_old_caches and refresh_pricing_data to ensure accurate calculations.

Frequently Asked Questions

How does TokenCost calculate API costs without impacting LLM performance?

The register_llm method in browser_use/tokens/service.py stores the original ainvoke coroutine and replaces it with a thin wrapper that records usage metadata after the LLM call completes. This design executes the original LLM invocation without modification, then fires asynchronous background tasks to log usage and calculate costs, ensuring zero latency impact on the critical path.

Where does the pricing data come from and how often is it updated?

The system fetches data from the LiteLLM repository's model_prices_and_context_window.json file. By default, this data is cached for 24 hours in ~/.cache/browser_use/token_cost. The _find_valid_cache method validates cache freshness, while _fetch_and_cache_pricing_data retrieves updates automatically when the cache expires or when manually triggered via refresh_pricing_data().

Can I use TokenCost with multiple different LLM providers simultaneously?

Yes. The TokenCost service maintains a dictionary of registered LLM instances and aggregates usage across all of them in the get_usage_summary method. The by_model field in the returned UsageSummary object breaks down costs per specific model (e.g., gpt-4, claude-3-opus), allowing you to compare expenses across different providers in a single analysis.

How do I prevent my agent from consuming unlimited tokens during debugging?

Always configure the max_agent_steps parameter in your agent configuration (as demonstrated in examples/01_basic_task.py). Additionally, enable cost tracking via the environment variable only during profiling runs—set BROWSER_USE_CALCULATE_COST=false in production to avoid the minimal overhead of usage recording when not needed.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →