Donner à un agent IA une recherche web en direct avec un plafond de dépense strict
Un agent qui cherche sur le web peut aussi boucler. Comment brancher la recherche en direct pour que le budget soit imposé par l'API, pas par le modèle.

Donner un outil de recherche à un modèle, c’est quatre lignes de code. Lui donner un outil de recherche qui ne peut pas vous coûter 4 000 $ en une nuit demande un peu plus de réflexion.
Le mode de défaillance est précis : un agent qui relance en boucle sur des résultats vides, ou qui décompose une seule question en quarante sous-requêtes, ou qui reste coincé dans une boucle planifier-chercher-replanifier. Rien de tout cela ne ressemble à un bug pendant que ça se produit. Ça ressemble à un agent qui travaille dur.
Ne comptez pas sur le prompt pour le budget
« Utilisez au maximum 5 recherches » dans un system prompt est une préférence, pas une limite. Ça se dégrade avec un contexte long, ça se fait écraser par un plan trop confiant, et ça disparaît complètement dès que l’agent reçoit une question réellement difficile.
Les limites de dépense doivent se trouver à trois endroits que le modèle ne peut pas contester.
Niveau 1 : un solde de crédits que le modèle ne peut pas dépasser
La limite la plus externe doit être la clé elle-même. Une clé avec un solde de crédits fini ne peut pas dépenser plus que ce solde, quoi que décide l’agent. Sur FastAF, le solde vit sur le compte et chaque requête réserve son coût avant que le travail ne commence, donc une boucle incontrôlée tombe sur 402 insufficient_credits et s’arrête.
Le solde appartient au compte, et toutes les clés de ce compte y puisent. Les clés servent à révoquer un accès (une par déploiement, pour couper seule une clé qui a fuité), pas à répartir l’argent : si un projet secondaire ne doit pas pouvoir vider le budget de votre pipeline de production, donnez-lui son propre compte avec son propre solde, rechargé délibérément.
Niveau 2 : un budget par exécution dans le wrapper de l’outil
À l’intérieur d’une seule exécution, comptez ce que vous dépensez et refusez d’aller plus loin. Chaque réponse porte son coût dans un en-tête, donc la comptabilité est exacte plutôt qu’estimée :
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="us"):
if self.spent + self.cost > self.max_credits:
# Renvoyé au modèle comme un résultat d'outil normal, pas une exception :
# l'agent doit pouvoir raisonner sur le fait qu'il n'a plus de budget.
return {"error": "search budget exhausted for this run"}
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": "out of credits"}
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,
}
Le contrôle porte sur spent + cost > max_credits, pas seulement sur spent : avec un budget de 6, ne contrôler que spent laisserait passer une deuxième recherche de 5 crédits, soit 10 au total.
Deux détails comptent plus qu’ils n’en ont l’air. D’abord, l’épuisement est renvoyé comme un résultat d’outil plutôt que levé comme une exception, pour que l’agent puisse s’adapter et répondre avec ce qu’il a au lieu de faire planter l’exécution. Ensuite, indiquer au modèle combien de budget il reste change son comportement de façon mesurable : les agents qui voient un budget qui rétrécit priorisent leurs requêtes.
Niveau 3 : réduisez ce qui repart dans le contexte
Une réponse SERP brute est volumineuse, et pousser tout ça dans le contexte coûte plus cher en tokens que le coût de la recherche en crédits. Renvoyer les cinq premiers résultats avec titre, lien et snippet suffit presque toujours pour que le modèle décide quoi lire en entier, et ça garde la boucle bon marché.
C’est aussi pourquoi « chercher » et « récupérer la page » doivent être deux outils séparés : laissez le modèle chercher à bas coût, puis payez la page entière uniquement pour les deux ou trois liens qu’il veut vraiment.
Niveau 4 : bornez la concurrence
Si votre agent lance des sous-requêtes en parallèle, plafonnez ce nombre au niveau ou en dessous de la limite de concurrence de votre plan. Au-delà, vous obtenez des réponses 429 avec un en-tête Retry-After, qu’une boucle de relance naïve transforme en rafale de requêtes dupliquées. Respectez l’en-tête, et gardez le pool de workers petit.
Vers quoi ça va
Aujourd’hui, la façon propre de brancher ça est un appel REST avec une clé scopée et un budget que vous imposez dans le wrapper, ce que fait le code ci-dessus. L’autre voie est que l’agent paie lui-même chaque appel, sans compte du tout. FastAF prend en charge x402 dès aujourd’hui sur tous les endpoints REST, à 0,001 USDC par crédit sur Base : une recherche Google coûte 0,005 $ et n’est prélevée que si l’appel réussit (MPP n’est pas pris en charge). Le plafond devient alors le solde du wallet, tandis qu’en volume les crédits prépayés restent moins chers. La documentation x402 montre le flux complet.
La documentation donne la liste complète des endpoints et la sémantique des erreurs, et la page tarifs donne le coût en crédits de chaque appel pour dimensionner correctement un budget par exécution.