Dare a un agente AI la ricerca web con un tetto di spesa
Un agente che può cercare sul web può anche entrare in loop. Come collegare la ricerca live a un agente in modo che il budget sia imposto dall'API, non dalla speranza che il modello si comporti bene.

Dare a un modello uno strumento di ricerca sono quattro righe di codice. Dargli uno strumento di ricerca che non possa costarti 4.000 dollari in una notte richiede qualche accortezza in più.
Il modo in cui va storto è preciso: un agente che riprova sui risultati vuoti, o che scompone una domanda in quaranta sotto-query, o che si incarta in un ciclo pianifica-cerca-ripianifica. Nessuno di questi sembra un bug mentre succede. Sembra un agente che lavora sodo.
Il budget non si mette nel prompt
“Usa al massimo 5 ricerche” in un system prompt è una preferenza, non un limite. Si degrada nei contesti lunghi, viene scavalcato da un piano convincente e sparisce del tutto appena l’agente riceve una domanda davvero difficile.
I limiti di spesa vanno messi in tre posti su cui il modello non può discutere.
Livello 1: un saldo crediti che il modello non può superare
Il limite più esterno deve essere la chiave stessa. Una chiave con un saldo finito non può spendere più di quel saldo, qualunque cosa decida l’agente. Su FastAF il saldo sta sull’account e ogni richiesta prenota il suo costo prima di partire, quindi un loop impazzito sbatte su 402 insufficient_credits e si ferma.
Il saldo appartiene all’account, e tutte le chiavi di quell’account attingono da lì. Le chiavi servono a revocare l’accesso (una per deployment, così una chiave trapelata si spegne da sola), non a dividere i soldi: se un progetto secondario non deve poter prosciugare il budget della pipeline di produzione, dagli un account suo con un saldo suo, ricaricato di proposito.
Livello 2: un budget per singola esecuzione
Dentro una singola run, conta quanto spendi e rifiuta di andare oltre. Ogni risposta porta con sé il proprio costo in un header, quindi la contabilità è esatta e non stimata:
import requests
class SearchBudget:
cost = 5 # credits per search
def __init__(self, api_key, max_credits=100):
self.api_key = api_key
self.max_credits = max_credits
self.spent = 0
def search(self, query, country="it"):
if self.spent + self.cost > self.max_credits:
# Restituito al modello come normale risultato del tool, non come
# eccezione: l'agente deve poter ragionare sul budget esaurito.
return {"error": "budget di ricerca esaurito"}
response = requests.get(
"https://api.fastaf.co/v1/serp",
params={"query": query, "country": country},
headers={"Authorization": f"Bearer {self.api_key}"},
timeout=60,
)
if response.status_code == 402:
return {"error": "crediti esauriti"}
if response.status_code != 200:
return {"error": response.json().get("error", {}).get("code", "search_failed")}
self.spent += int(response.headers.get("X-FastAF-Credits-Used", 5))
data = response.json()
return {
"results": [
{"title": r["title"], "link": r["link"], "snippet": r.get("snippet")}
for r in data.get("organic_results", [])[:5]
],
"credits_remaining": self.max_credits - self.spent,
}
Il controllo è spent + cost > max_credits, non solo spent: con un budget di 6, controllare solo spent lascerebbe passare una seconda ricerca da 5 crediti, per 10 in totale.
Due dettagli contano più di quanto sembri. Primo: l’esaurimento torna come risultato del tool e non come eccezione, così l’agente può adattarsi e rispondere con quello che ha invece di far crashare la run. Secondo: dire al modello quanto budget resta ne cambia il comportamento in modo misurabile, perché un agente che vede il budget calare mette in ordine di priorità le proprie query.
Livello 3: taglia quello che torna nel contesto
Una risposta SERP grezza è grossa, e riversarla tutta nel contesto costa in token più di quanto la ricerca sia costata in crediti. Restituire i primi cinque risultati con titolo, link e snippet basta quasi sempre al modello per decidere cosa leggere per intero, e mantiene il ciclo economico.
È anche il motivo per cui “cerca” e “scarica la pagina” devono essere due strumenti separati: il modello cerca a poco prezzo, e paga la pagina intera solo per i due o tre link che gli servono davvero.
Livello 4: limita la concorrenza
Se l’agente lancia sotto-query in parallelo, tieni il ventaglio pari o inferiore al limite di concorrenza del piano. Sopra quel limite arrivano risposte 429 con header Retry-After, che un retry ingenuo trasforma in una raffica di richieste duplicate.
Dove sta andando
Oggi il modo pulito è una chiamata REST con una chiave dedicata e un budget imposto nel wrapper, come nel codice qui sopra. L’altra strada è l’agente che paga da solo ogni chiamata, senza nemmeno un account. FastAF supporta x402 già oggi su tutti gli endpoint REST, a 0,001 USDC per credito su Base: una ricerca Google costa 0,005 $ e viene addebitata solo se la chiamata va a buon fine (MPP non è supportato). Il tetto diventa il saldo del wallet, mentre sui volumi i crediti prepagati restano più convenienti. La documentazione x402 mostra il flusso completo.
Nella documentazione trovi la lista completa degli endpoint e la semantica degli errori, e nei prezzi il costo in crediti di ogni chiamata.