ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Add Search Budget Caps to an AI Agent
Tutorial

How to Add Search Budget Caps to an AI Agent

Stop runaway search API spend in AI agents. Implement a credit counter decorator in Python that halts searches after a per-session or per-run limit.

Get Free API KeyAPI Docs

A search budget cap stops an AI agent from burning through API credits in a single runaway loop. The pattern wraps your search function with a decorator that tracks cumulative spend and raises an exception when the limit is hit.

Prerequisites

  • Python 3.9+
  • Scavio API key
  • requests library

Walkthrough

Step 1: Create the budget tracker class

A simple class holds the credit count and raises BudgetExceeded when the cap is hit.

Python
class BudgetExceeded(Exception):
    def __init__(self, used, cap):
        super().__init__(f"Search budget exceeded: {used}/{cap} credits used")
        self.used = used
        self.cap = cap

class SearchBudget:
    def __init__(self, cap_credits: float):
        self.cap = cap_credits
        self.used = 0.0

    def charge(self, credits: float):
        self.used += credits
        if self.used > self.cap:
            raise BudgetExceeded(self.used, self.cap)

    def remaining(self) -> float:
        return max(0, self.cap - self.used)

Step 2: Build the budget-aware search decorator

Wrap the raw API call. Each request costs 1 credit by default; adjust if you use bulk endpoints.

Python
import functools
import requests

def with_budget(budget: SearchBudget, credits_per_call: float = 1.0):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            budget.charge(credits_per_call)
            return fn(*args, **kwargs)
        return wrapper
    return decorator

Step 3: Apply to your search function

Create a session budget and decorate the search call before passing it to your agent.

Python
API_KEY = "your-scavio-api-key"

def _raw_search(query: str, **kwargs) -> dict:
    payload = {"query": query, "num_results": kwargs.get("num_results", 10)}
    if kwargs.get("platform"):
        payload["platform"] = kwargs["platform"]
    r = requests.post(
        "https://api.scavio.dev/api/v1/search",
        json=payload,
        headers={"x-api-key": API_KEY},
        timeout=15
    )
    r.raise_for_status()
    return r.json()

# Cap at 20 credits per agent run (~$0.10)
budget = SearchBudget(cap_credits=20)
search = with_budget(budget)(_raw_search)

try:
    results = search("python async best practices")
    print(f"Credits remaining: {budget.remaining()}")
except BudgetExceeded as e:
    print(f"Stopped: {e}")

Step 4: Integrate with an agent loop

Pass the budget-capped search to your agent and catch BudgetExceeded to return partial results gracefully.

Python
def run_research_agent(topic: str, max_credits: int = 15):
    budget = SearchBudget(cap_credits=max_credits)
    search = with_budget(budget)(_raw_search)
    findings = []

    subtopics = [topic, f"{topic} tutorial", f"{topic} examples", f"{topic} best practices"]

    for subtopic in subtopics:
        try:
            data = search(subtopic)
            findings.extend(data.get("organic_results", [])[:3])
            print(f"Searched '{subtopic}' | {budget.remaining():.0f} credits left")
        except BudgetExceeded as e:
            print(f"Budget cap hit after {e.used} credits. Returning partial results.")
            break

    return findings

results = run_research_agent("vector databases", max_credits=5)
print(f"Got {len(results)} results")

Python Example

Python
import functools
import requests

class BudgetExceeded(Exception):
    def __init__(self, used, cap):
        super().__init__(f"Search budget exceeded: {used:.1f}/{cap} credits")
        self.used = used
        self.cap = cap

class SearchBudget:
    def __init__(self, cap_credits: float):
        self.cap = cap_credits
        self.used = 0.0

    def charge(self, credits: float = 1.0):
        self.used += credits
        if self.used > self.cap:
            raise BudgetExceeded(self.used, self.cap)

    def remaining(self) -> float:
        return max(0.0, self.cap - self.used)

API_KEY = "your-scavio-api-key"

def _raw_search(query: str, platform: str = None, num_results: int = 10) -> dict:
    payload = {"query": query, "num_results": num_results}
    if platform:
        payload["platform"] = platform
    r = requests.post(
        "https://api.scavio.dev/api/v1/search",
        json=payload,
        headers={"x-api-key": API_KEY},
        timeout=15
    )
    r.raise_for_status()
    return r.json()

def make_capped_search(cap_credits: float):
    budget = SearchBudget(cap_credits)
    def search(query: str, **kwargs) -> dict:
        budget.charge(1.0)
        result = _raw_search(query, **kwargs)
        result["_budget"] = {"used": budget.used, "remaining": budget.remaining()}
        return result
    search.budget = budget
    return search

if __name__ == "__main__":
    search = make_capped_search(cap_credits=5)
    queries = [
        "best vector databases 2026",
        "vector database comparison",
        "pinecone vs weaviate vs chroma",
        "vector db benchmarks",
        "vector database pricing",
        "vector db tutorial",  # This should trigger BudgetExceeded
    ]
    for q in queries:
        try:
            data = search(q)
            top = data.get("organic_results", [{}])[0]
            print(f"[{search.budget.used:.0f}/{search.budget.cap}] {top.get('title', 'no title')}")
        except BudgetExceeded as e:
            print(f"Stopped: {e}")
            break

JavaScript Example

JavaScript
const API_KEY = 'your-scavio-api-key';

class BudgetExceeded extends Error {
  constructor(used, cap) {
    super(`Search budget exceeded: ${used}/${cap} credits`);
    this.used = used;
    this.cap = cap;
  }
}

function makeCappedSearch(capCredits) {
  let used = 0;

  async function search(query, { platform, numResults = 10 } = {}) {
    used += 1;
    if (used > capCredits) throw new BudgetExceeded(used, capCredits);

    const payload = { query, num_results: numResults };
    if (platform) payload.platform = platform;

    const res = await fetch('https://api.scavio.dev/api/v1/search', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
      body: JSON.stringify(payload)
    });
    if (!res.ok) throw new Error(`Search failed: ${res.status}`);
    const data = await res.json();
    data._budget = { used, remaining: Math.max(0, capCredits - used) };
    return data;
  }

  search.getUsed = () => used;
  return search;
}

const search = makeCappedSearch(5);
const queries = ['vector databases 2026', 'pinecone vs chroma', 'vector db pricing', 'weaviate tutorial', 'qdrant setup', 'overflow query'];

for (const q of queries) {
  try {
    const data = await search(q);
    const top = data.organic_results?.[0];
    console.log(`[${data._budget.used}/${5}] ${top?.title ?? 'no title'}`);
  } catch (e) {
    if (e instanceof BudgetExceeded) { console.log(`Stopped: ${e.message}`); break; }
    throw e;
  }
}

Expected Output

JSON
[1/5] Top 10 Vector Databases in 2026
[2/5] Vector Database Comparison: Pinecone vs Chroma vs Weaviate
[3/5] Vector Database Pricing Guide 2026
[4/5] Weaviate Getting Started Tutorial
[5/5] Qdrant Setup and Configuration
Stopped: Search budget exceeded: 6/5 credits

Related Tutorials

  • How to Set Up a Search API Failover Pattern
  • How to Ground LLM Output with Live SERP Data
  • How to Build a Multi-Source Research Agent

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.9+. Scavio API key. requests library. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Workflow

Agent Search Cost and Budget Tracking Workflow

Read more
Best Of

Best Budget Search APIs for AI Agents Under $10/mo (2026)

Read more
Use Case

Agent Search Cost Control

Read more
Best Of

Best Search APIs for Budget Agent Builders in 2026

Read more
Solution

Route Agent Searches to the Cheapest Provider Automatically

Read more
Use Case

Budget-Controlled Agent Search

Read more

Start Building

Stop runaway search API spend in AI agents. Implement a credit counter decorator in Python that halts searches after a per-session or per-run limit.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy