← Blog

AI agents

Autonome agent: €2.140 verbrand op een Bol.com-captcha

Een research-agent draaide vier uur 's nachts. 's Ochtends stond de teller op €2.140 aan residentiële proxies, allemaal voor dezelfde captcha op Bol.com. Wat er misging.

Jacob Molkenboer· Oprichter · A Brand New Company· 29 mei 2025· 9 min
Messing buispostkoker open op ivoorkleurig papier, kassabon ontrold, limoengroen memoblaadje op de zijkant.

De telefoon van de CFO trilde donderdag om 06:42 met een Bright Data-factuuralert. Toen de ops-lead in Almere om 08:10 achter haar laptop ging zitten, stond de teller op €2.140,18. De dader was een research-agent die de nacht ervoor om 02:30 was gestart door een junior analist die “een schone export van Bol.com-sneakerprijzen vóór 09:00” wilde. De agent hield zijn belofte op de duurste manier denkbaar. Hij hamerde ongeveer 4.800 keer op dezelfde Bol.com-zoekpagina, elke poging via een ander residential IP, elke keer geblokt door dezelfde captcha, elke retry een paar cent bandbreedte op de rekening.

Dit is hoe dat kon gebeuren, wat we vonden toen we de logs lazen, en de vier controles die wij nu standaard op elke agent zetten die met een betaald netwerk praat.

De opzet

Het bedrijf verkoopt programmatic ad inventory aan Nederlandse e-commercemerken. Negentien mensen, een klein ops-team, geen vaste platform engineer. Drie maanden geleden ging het analyseteam aan de slag met een populair open-source agent framework om concurrentieprijzen te scrapen. De agent had toegang tot een headless browser, een Bright Data residential proxy en een Postgres database. De system prompt droeg hem op om “te blijven proberen tot je de data hebt”.

Die laatste instructie klinkt onschuldig. Dat is hij niet. We zijn dit kwartaal dezelfde zin tegengekomen in drie verschillende agent-stacks, en het is de duurste zin in moderne AI-engineering.

De run van woensdagnacht begon normaal. De agent haalde de eerste Bol.com-zoekpagina op, parsete hem, sloeg tien rijen op. Op pagina twee gaf Bol.com een captcha-challenge terug. De vision-tool van de agent kon hem niet oplossen. De planner concludeerde dat de pagina niet goed geladen was. Hij probeerde opnieuw. Ander IP, dezelfde captcha. Nog een keer. De proxy-rotatie bleef nieuwe residential exits aanleveren, die Bol.com elk binnen milliseconden flagde.

Om 03:00 draaide de loop op ongeveer twintig requests per minuut. Om 06:00 was de residential bandwidth-teller voorbij de €1.500. Het Bright Data-dashboard heeft wel spend alerts, maar die waren ingesteld op het verbruik van het vorige kwartaal, en de alertmail kwam binnen in een gedeelde mailbox die 's nachts niemand bekijkt.

Waarom de loop nooit brak

Er moesten drie dingen achter elkaar misgaan.

Eén: de agent had geen begrip van kosten. Voor hem was de proxy een tool die ofwel een pagina teruggaf, ofwel niet. Een captcha zag zijn parser als een pagina die “niet correct geladen was”. De default retry policy van het framework was “exponential backoff tot tien pogingen”, maar die teller werd gereset elke keer dat de planner de scrape-stap opnieuw binnenkwam. Omdat de planner bleef beslissen dat “we de tweede pagina met resultaten nog steeds nodig hebben”, werd die cap van tien pogingen feitelijk nooit bereikt.

Twee: de proxy rekent per gigabyte residential traffic af, niet per request. Bright Data's residential pricing begint op dit moment rond de $8,40 per GB pay-as-you-go en daalt bij volume-afspraken. Een Bol.com-zoekpagina weegt ruwweg 1,2 MB zodra de afbeeldingen en de captcha-widget geladen zijn. Vermenigvuldig dat met 4.800 pogingen en je zit op ongeveer 5,6 GB. Tel daar de screenshot-calls bij op plus een handvol retries op de productpagina's die hij eerder in de run wel bereikt had, en €2.140 is opeens geen verrassing meer.

Drie: niemand keek de agent ooit op de vingers. Het team had een Slack-kanaal voor agent-output, maar de agent postte alleen bij “task complete” of “task failed”. Een loop die eeuwig blijft retryen zit in geen van beide states.

Let op

Als je agent alleen meldt op terminal states, is een oneindige loop per ontwerp onzichtbaar. De kostenteller is het enige dat nog beweegt.

Het patroon dat steeds terugkomt

Als dit bekend in de oren klinkt: dezelfde vorm dook dit jaar op in meerdere agent-post-mortems. De autonome reconnaissance-agent van één operator stookte een rekening met vier cijfers leeg op het DN42-netwerk, omdat geweigerde TCP-connecties door de planner steeds gelezen werden als “probeer een andere route”. Ander domein, hetzelfde patroon. Een agent met een doel, een betaalde resource en de instructie om door te gaan. Een target die dubbelzinnige antwoorden geeft. Een planner die elke cyclus dezelfde stap opnieuw binnenkomt. Een rekening die meetkundig groeit terwijl de operator slaapt.

Het opvallende aan deze incidenten is dat de agents niet kapot gingen. Ze deden precies wat hun prompts opdroegen. De fout zat in het systeem eromheen: geen spend ceiling, geen circuit breaker op herhaalde identieke acties, geen leesbare heartbeat voor mensen.

De huidige discussie over proactieve agents behandelt “agent doet te veel” als een UX-probleem. Het essay Building effective agents beschrijft de call-and-response loop helder genoeg vanuit de designkant. Nadat we deze incident-logs achter elkaar gelezen hadden, denken wij dat het grotere probleem eerst financiële controls is, en pas daarna UX.

Wat de logs daadwerkelijk lieten zien

We dumpten het traject van de agent in een spreadsheet. Van de 4.812 tool calls gingen er 4.798 naar hetzelfde fetch_url-endpoint met dezelfde URL. De overgebleven veertien waren screenshot_page-calls (waarmee het vision-model de captcha inspecteerde) en één write_database-call uit de eerste succesvolle scrape, rond 02:34.

De redeneerstappen van de planner, op volgorde gelezen, zagen er zo uit:

Step 23: Page did not return the expected product grid. Retrying.
Step 24: Page still missing product grid. Possible network issue.
         Retrying with different proxy.
Step 25: Possible bot detection. Retrying with different proxy.
Step 26: Page did not return expected content. Retrying.
[continues for 4,770 more steps]

De planner escaleerde nooit. Hij schreef nooit “ik heb het vijftig keer geprobeerd en de pagina laat steeds iets zien dat op een captcha lijkt. Ik moet stoppen en om hulp vragen”. Hij had geen begrip van “ik heb het vijftig keer geprobeerd”, omdat niets in de loop een teller ophoogde die de re-planning overleefde.

De vier controles die wij nu op elke agent zetten

Wij denken niet dat dit soort incidenten te voorkomen is met een betere prompt. De prompt staat te ver van de kosten af. De controls moeten een laag lager zitten, tussen de agent en de betaalde resource.

Een harde budget-cap op de proxy-laag

Stel een dag- en uurcap in in het dashboard van je proxyleverancier. Bright Data, Oxylabs, Smartproxy en de rest ondersteunen dit allemaal. Kies een getal dat twee of drie keer je normale dagverbruik is, niet tien keer. De cap moet afgaan voordat de rekening pijn doet. Stuur de alertmail naar een kanaal dat iemand echt in de gaten houdt, niet de privé-inbox van de analist.

Een circuit breaker op identieke acties

De agent-runtime, niet de agent zelf, moet detecteren dat de laatste N tool calls identiek waren en de laatste N responses structureel hetzelfde, en dan de volgende call weigeren. We zetten N meestal eerst op vijf en stellen vandaaruit bij. De runtime geeft een error terug aan de planner die luidt “circuit breaker tripped: identical tool call repeated five times. Try a different approach or escalate”. De meeste planners stoppen daarop. De paar die dat niet doen, vang je met de volgende control.

Een wall-clock heartbeat naar een menselijk kanaal

Elke vijftien minuten post de agent één regel status in Slack: huidige taak, laatst succesvolle tool call, aantal tool calls in deze planning-cyclus. Iemand die overdag even het kanaal bekijkt, vangt de loop binnen één cyclus. De juiste vorm lijkt meer op de progress-regel van een build server dan op een chatbericht. Stille successen zijn prima. Negentig minuten stilte niet.

Een aparte kill switch voor betaalde tools

De goedkoopste fix is ook de simpelste. Geef elke betaalde tool zijn eigen per-run quotum dat de agent niet kan overrulen. Als het quotum 200 fetch_url-calls is en de agent maakt de 201e, killt de runtime de run en piept de on-call op. De prompt van de agent hoeft niet eens te weten dat het quotum bestaat. Dit is de control die het donderdagincident een voetnoot had gemaakt in plaats van een terugbetalingsgesprek.

Inzicht

Een agent die met een metered API praat is een financieel systeem. Behandel hem zo: budgets, circuit breakers, heartbeats, kill switches. De prompt is geen control.

Specifiek over captchas

Captchas zijn geen tijdelijke netwerkfout en je agent moet ze ook niet zo behandelen. Als een pagina twee keer achter elkaar vanaf twee verschillende IPs een captcha-challenge geeft, heeft de target site besloten dat jouw agent een bot is, en daar verander je op korte termijn niets aan met proxy-rotatie. Het juiste gedrag is: stoppen, de URL in een queue zetten, en óf escaleren naar een mens óf wachten tot de risicoscore van de site voor het oorspronkelijke signaal weer gezakt is.

De goedkoopste detectie is een string match op de response body voor het domein van de captcha-leverancier (hCaptcha, reCAPTCHA, Cloudflare Turnstile, de eigen challenge van Bol.com). De volgende stap omhoog is een kleine classifier op een screenshot. Beide hadden deze run binnen een minuut beëindigd.

Wat dit bedrijf op donderdag deed

Wij hielpen ze het terugbetalingsverzoek schrijven. Bright Data, alle credits ervoor, vergoedde het grootste deel van de uitgave nadat het team de trajectory-log en de timestamps aanleverde. Niet elke leverancier doet dit, en het bedrijf behandelt het krediet inmiddels als eenmalige coulance, niet als strategie.

Het team herschreef ook de scrape-stap van de agent. Hij gebruikt nu de affiliate-feed API van Bol.com voor catalogusdata, valt alleen terug op een headless browser voor velden die de API niet teruggeeft, en routeert pas via residential proxies als de headless-poging daadwerkelijk een non-captcha response oplevert. Op die fallback zit een per-task budget van 50 MB residential traffic. Als dat budget afgaat, schrijft de agent een rij in een needs_human-tabel en stopt.

De framework-upgrade kostte twee engineering-dagen. Residential proxy-spend in de eerste week na de wijziging was €37.

Het kleinste dat je vandaag kunt doen

Als je één autonome agent draait die een betaalde API aanraakt, open dan nu het dashboard van die leverancier en zet een daily spend cap op twee keer het gemiddelde van vorige week. Die ene verandering had het donderdagincident afgekapt op ongeveer €60. Toen wij vorig kwartaal de research- en pricing-agents bouwden voor een klant in Eindhoven, kwam dezelfde les telkens terug: de goedkope controls (een cap, een teller, een heartbeat) werken beter dan de slimme. Wil je hulp om die in je eigen AI-agents te bouwen zonder de hele stack te herbouwen, dat is het soort werk dat wij doen.

Kern

Een agent die met een metered API praat is een financieel systeem. Budgets, circuit breakers, heartbeats en kill switches zijn belangrijker dan hoe je de prompt formuleert.

FAQ

Hoe kon één captcha €2.140 kosten?

De agent probeerde dezelfde geblokte pagina in vier uur ongeveer 4.800 keer opnieuw, elke keer via een vers residential IP. Residential proxies rekenen per gigabyte af, en dat aantal captcha-pagina's loopt snel op.

Waarom redde de retry-cap van het framework ze niet?

De cap van tien pogingen werd gereset elke keer dat de planner de scrape-stap opnieuw binnenkwam. Omdat de planner bleef beslissen dat de scrape nog moest, raakte die teller nooit zijn limiet.

Wat is de goedkoopste control om vanavond nog toe te voegen?

Een daily spend cap in het dashboard van je proxyleverancier, ingesteld op twee of drie keer je normale gebruik. Daarmee was dit incident afgekapt op ongeveer €60 in plaats van €2.140.

Mag een agent ooit een captcha opnieuw proberen?

Nee. Twee captchas op rij vanaf verschillende IPs betekent dat de site jouw agent als bot heeft geclassificeerd. Het juiste gedrag is stoppen, de URL in een queue zetten en escaleren naar een mens of lang wachten.

ai agentsautomationcase studyarchitectureoperationstooling

Iets bouwen?

Start een project