Alejandro Rioja.
AI Agents Operations

Een AI-agent debuggen in productie (een praktijkgids)

Alejandro Rioja
Alejandro Rioja
7 min lezen
TL;DR

Een AI-agent in productie debuggen draait vooral om isoleren welke laag faalde — prompt, tool, model of orkestratie. Ik log elke stap met een trace-ID, speel de exacte invoer opnieuw af en bisecteer. In mijn agents blijkt ~70% van de 'AI-bugs' loodgieterswerk-bugs te zijn, geen modelbugs.

Gratis nieuwsbrief

Elke woensdag. 28.400+ operators. Geen opvulling.

Inhoudsopgave

Bijgewerkt juni 2026.

TL;DR: Een AI-agent in productie debuggen draait vooral om isoleren welke laag faalde — prompt, tool-aanroep, modeluitvoer of orkestratie. Ik log elke stap met een trace-ID, speel de exacte invoer opnieuw af en bisecteer van daaruit. In mijn agents blijkt ongeveer 70% van wat op een “AI-bug” lijkt loodgieterswerk te zijn: een misvormd toolresultaat, een afgekapte invoer, een stilletjes opgeslokte exceptie.

Blik van de operator: Ik draai meer dan 100 productie-agents — boekingsflows voor Pickleland, contentpipelines, inbox-triagers. Ze breken zoals alle software breekt, plus een paar nieuwe manieren. Dit is de praktijkgids die ik graag had gehad: hoe je de falende laag vindt zonder naar een muur van tokens te staren.

Wanneer een agent zich misdraagt in productie, is het instinct om het model de schuld te geven. “Claude hallucineerde.” Soms waar. Meestal niet. Het model is één laag in een stapel van vijf of zes, en de bug zit veel vaker in de laag die jij schreef dan in die welke Anthropic uitbracht. Deze post is de systematische manier waarop ik hem vind.

Maak elke run traceerbaar voordat je ook maar iets debugt

Je kunt niet debuggen wat je niet kunt zien. Het meest hefboomwerkende wat je kunt doen — voordat er een specifieke bug opduikt — is een trace-ID aan elke agent-run hangen en elke stap die hij zet loggen.

Een “stap” is alles wat een grens overschrijdt: de inkomende trigger, elke modelaanroep (met de volledige messages-array), elke tool-aanroep (met argumenten), elk toolresultaat en de uiteindelijke uitvoer. Log ze als gestructureerde JSON, geïndexeerd op de trace-ID.

typescript
function logStep(traceId: string, step: string, payload: unknown) {
  console.log(JSON.stringify({
    traceId,
    step,            // "trigger" | "model_call" | "tool_call" | "tool_result" | "output"
    ts: Date.now(),
    payload,
  }));
}

Op Cloudflare Workers stuur ik deze naar een queue en in een tabel; lokaal gaan ze naar stdout. De regel is absoluut: als een stap niet gelogd is, dan is hij wat debuggen betreft niet gebeurd. Dit weerspiegelt de instrumentatie die ik beschrijf in de agent-stack die ik gebruik — de trace-ID is de ruggengraat waar al het andere aan hangt.

Isoleer de laag: prompt, tool, model of orkestratie

Zodra je een trace hebt, wordt debuggen een bisectie. Er zijn vier lagen en de bug woont meestal in precies één ervan.

1. De invoerlaag (de meest voorkomende boosdoener)

Haal de exacte messages-array tevoorschijn die de gefaalde modelaanroep inging. Geen reconstructie — de letterlijke payload uit de log. Lees hem dan zoals een vreemde zou doen. De helft van mijn “het model negeerde de instructies”-bugs zijn eigenlijk:

Als de invoer fout is, deed het model zijn werk perfect op rommel. Repareer het loodgieterswerk.

2. De toollaag

Als de invoer er schoon uitziet, controleer dan of een tool een fout teruggaf die de agent als succes behandelde. Een klassieker: een API geeft 200 terug met een body van { "error": "rate limited" }, je tool-wrapper controleert de body niet, en de agent handelt vol vertrouwen naar een foutmelding. Log toolresultaten ruw en valideer hun vorm.

3. De modellaag

Pas nadat ik 1 en 2 heb uitgesloten, verdenk ik het model. Zelfs dan betekent “modelbug” meestal “mijn prompt is dubbelzinnig.” Neem de exacte gefaalde invoer, gooi hem in een wegwerpscript tegen hetzelfde model en dezelfde temperatuur, en kijk of het reproduceert. Als het reproduceert, is de oplossing promptwerk of een strakkere eval, geen paniekerige modelwissel.

4. De orkestratielaag

Als één stap op zichzelf prima is maar de meerstapsrun faalt, zit de bug in de overdracht — verloren staat tussen stappen, een race condition, een retry die een niet-idempotente actie opnieuw uitvoerde. Dit zijn de vervelendste en ik behandel de patronen in multi-agent-orkestratiepatronen.

Reproduceer non-determinisme in plaats van ertegen te vechten

Wat agents ondebugbaar doet aanvoelen, is non-determinisme: dezelfde invoer levert verschillende uitvoer op over runs heen. Je kunt het temmen.

Ten eerste, zet vast wat je kunt. Stel temperature: 0 in tijdens het debuggen. Het maakt Claude niet volledig deterministisch, maar het versmalt de variantie sterk zodat je een echte bug van samplingruis kunt onderscheiden.

Ten tweede, draai hem N keer. Als een fout 1 op de 20 runs reproduceert, loop dan de exacte invoer 50 keer en leg elke uitvoer vast. Nu heb je een steekproef, geen anekdote. Een bug die 5% van de tijd afgaat, is een echte bug — je hebt alleen volume nodig om hem te zien.

bash
for i in $(seq 1 50); do
  node replay.mjs --trace=abc123 >> runs.jsonl
done
# tel daarna de fouten
grep -c '"status":"fail"' runs.jsonl

Ten derde, diff de geslaagde en gefaalde runs. Met de temperatuur vastgezet en dezelfde invoer betekent een verschil in uitvoer een verschil in invoer dat je nog niet hebt opgemerkt — een tijdstempel in de prompt, een toolresultaat dat varieert, een opgehaald document dat veranderde.

Bouw een replay-harnas zodat je stopt met debuggen in productie

Debuggen door de live agent opnieuw te triggeren is traag en riskant — hij verstuurt echte e-mails, boekt echte banen. Leg in plaats daarvan de trace vast en speel hem offline opnieuw af.

Het replay-harnas laadt een gelogde trace, reconstrueert de exacte invoer voor elke willekeurige stap en draait alleen die stap opnieuw tegen het model. Omdat je de volledige messages-array hebt gelogd, heb je het upstream-systeem helemaal niet nodig. Dit verandert een retourtje van 10 minuten in productie in een lokale lus van 2 seconden, en het is de grootste versnelling in mijn debug-workflow.

Een goed replay-harnas laat je ook muteren en opnieuw draaien: verander één regel van de systeemprompt, speel dezelfde 50 gefaalde traces opnieuw af en kijk hoeveel er nu slagen. Dat is de brug van debuggen naar eval — zodra je een corpus van gefaalde traces hebt, heb je het begin van een regressiesuite.

Houd de metrieken in de gaten die breuk echt voorspellen

Sommige fouten gooien nooit een exceptie. De agent draait, geeft iets plausibels terug en doet stilletjes het verkeerde. Om die te vangen houd je gedragsmetrieken in de gaten, niet alleen foutpercentages:

Ik volg deze net zoals ik al het andere volg — zie hoe ik meet of een AI-agent daadwerkelijk werkt. De metriek die een stille fout vangt is er tien waard die luide vangen.

De triage-checklist van 5 minuten

Wanneer een agent breekt en de klok tikt, draai ik dit in volgorde:

  1. Haal de trace-ID van de gefaalde run.
  2. Lees de exacte invoer voor de gefaalde stap. Is hij goed gevormd? (Lost hier ~50% van de gevallen op.)
  3. Controleer de toolresultaten in die trace op fouten vermomd als succes.
  4. Speel de stap offline opnieuw af op temperature: 0. Reproduceert hij?
  5. Als hij reproduceert, is het een prompt-/modelprobleem — repareer en draai het trace-corpus opnieuw. Zo niet, dan is het non-determinisme of een staat-/orkestratiebug — loop hem 50× om hem te karakteriseren.

Gedisciplineerde isolatie verslaat slimme prompting elke keer. Het model is zelden het probleem; het systeem eromheen meestal wel.

FAQ

Hoe debug ik een AI-agent die maar soms faalt?

Leg de exacte invoer vast uit een gelogde trace en speel hem 50+ keer opnieuw af op temperatuur 0. Intermitterende fouten zijn echte bugs met lage afgaanpercentages — volume verandert de anekdote in een reproduceerbare steekproef die je kunt diffen en repareren.

Zit de bug meestal in het model of in mijn code?

In mijn productie-agents is ongeveer 70% van de schijnbare “AI-bugs” loodgieterswerk: misvormde toolresultaten, afgekapte invoer, opgeslokte excepties of verloren staat tussen stappen. Sluit de invoer- en toollagen uit voordat je het model verdenkt.

Wat is de minimale logging die ik nodig heb om agents te debuggen?

Een trace-ID op elke run, plus gestructureerde logs van de trigger, elke modelaanroep (volledige messages-array), elke tool-aanroep en het ruwe resultaat ervan, en de uiteindelijke uitvoer. Als een stap niet gelogd is, kun je hem niet debuggen.

Hoe stop ik met debuggen tegen de live productie?

Bouw een replay-harnas dat een gelogde trace laadt en elke afzonderlijke stap offline opnieuw uitvoert met de vastgelegde invoer. Het verandert een traag, riskant productieretourtje in een snelle lokale lus en wordt het zaadje van je regressiesuite.

Lees verder

Ontvang het AI-playbook in je inbox

Elke woensdag. 28.400+ operators. Geen opvulling.

↵ alle resultaten bekijken esc esc om te sluiten