Je wordt op een maandagochtend wakker met vijf kritieke bugrapporten. Je monitoringtool heeft zijn werk gedaan. Het heeft elk crashrapport gevangen, elke boze één-ster-review, elke "app bevriest als ik op opslaan tik". Je weet precies wat er kapot is. Wat je niet weet, is waar je moet zoeken.

Dat was de muur waar ik tegenaan liep na het bouwen van mijn eerste pipeline. Het monitorde app-reviews en inkomende crashlogs zonder problemen en sorteerde elk stukje feedback in nette categorieën: bugs, crashes of featureverzoeken. Het dashboard zag er gezond uit. Het eigenlijke debugproces niet.

Weten dat er een bug bestaat, is slechts het begin van een lange weg. Ik moest nog steeds de IDE openen, door modules 'greppen', stack traces vergelijken met de huidige codebase en het foutpad in mijn hoofd reconstrueren. Wanneer de tickets zich opstapelen en de koffie nog heet is, kost die handmatige archeologie tijd die je niet hebt. Ik had de pipeline nodig om meer te doen dan alleen problemen signaleren. Ik had hem nodig om ze te onderzoeken.

Dus ik heb het systeem opnieuw opgebouwd rondom één enkel doel: een ruw bugrapport nemen en een gevalideerde diagnose teruggeven. Geen paragraaf met LLM-overpeinzingen. Een gestructureerde bevinding die het bestand benoemt, naar de regel wijst, het risico inschat en een oplossing voorstelt. Zo is het tot stand gekomen.

Waarom structuur beter is dan een chatlog

Ik heb de onderzoekende agent gebouwd met PydanticAI. De reden was simpel. Wanneer je een taalmodel vraagt om over code te redeneren, is de standaardoutput een vriendelijke stroom tekst. Dat helpt misschien een menselijke lezer, maar het is nutteloos voor een downstream script. Ik had een machineleesbaar contract nodig.

De agent geeft een gevalideerd datamodel terug met vier specifieke velden: de hoofdoorzaak, de getroffen bestanden, de voorgestelde wijzigingen en een beoordeling van de complexiteit en het risico. Als het model een veld mist of een bestandspad hallucineert, mislukt de validatie en vang ik dat onmiddellijk op. Die strengheid houdt de pipeline eerlijk.

Om het echte detectivewerk te doen, krijgt de agent vier read-only tools en niets anders. Hij kan code doorzoeken via grep, specifieke regelbereiken uit een bestand lezen, de inhoud van een directory opnoemen en symbolen zoals klassen of functies lokaliseren. 'Read-only' is het belangrijkste deel. Ik wilde geen agent met schrijfrechten die om 2 uur 's nachts door mijn repository dwaalt. Eerst begrijpen, dan bewerken.

De Repo Map: Context vóór de tools

De eerste versie van de agent was accuraat, maar extreem duur. Het verbruikte tokens alsof het een toerist was die in cirkels liep. Het model riep list-dir aan, dan grep, dan een bestand uit, en dan weer list-dir, waarbij het langzaam en met dure tokens één voor één een mentaal model van de projectstructuur opbouwde.

De oplossing was om een compacte repo map te genereren voordat de agent überhaupt begint. Deze map is een samengevat overzicht van de repository: belangrijke bestanden, hun primaire functies of klassen, en hoe de belangrijkste modules met elkaar verbonden zijn. Zie het als het overhandigen van een GPS aan de agent, in plaats van hem te vragen de wegen door middel van trial-and-error te ontdekken.

Met die map in zijn context window verspilt de agent geen calls om erachter te komen dat src/utils/parser.ts bestaat. Hij kent het terrein al. Hij gaat rechtstreeks naar de bergkam waar de rook opstijgt. Die enkele wijziging elimineerde de zoekfase volledig.

De Tool Funnel: Een conclusie afdwingen

Zelfs met een map kon de agent blijven twijfelen. Hij zou een verdacht bestand vinden, zichzelf dan in twijfel trekken, dan opnieuw zoeken, dan een ander bestand lezen, gevangen in een eindeloze lus van "nog één controle". Ik had een manier nodig om momentum af te dwingen.

Ik heb een tool funnel in drie fasen geïmplementeerd die beperkt wat de agent kan doen naarmate hij vordert.

Fase één is exploratie. De agent heeft volledige toegang tot alle vier de tools. Hij kan zoeken, browsen en lezen wat hij nodig heeft om de bug in zijn redenering te reproduceren.

Fase twee is een deep-dive. Zodra de agent de waarschijnlijke foutlijnen heeft geïdentificeerd, verliest hij de ontdekkings-tools. Hij kan alleen nog bestanden lezen. Geen grep meer, geen directory-listings meer. In deze fase moet hij de code die hij al heeft gevonden bestuderen en zijn bewijsketen opbouwen.

Fase drie is output. Alle tools zijn vergrendeld. De agent kan de codebase niet meer bevragen. Hij moet gaan zitten en het rapport schrijven. Dit voorkomt de eindeloze "laat me nog even één ding checken"-spiraal.

Die funnel verlaagde het gemiddelde aantal tool calls van meer dan veertig per analyse naar ongeveer tien. De agent werd sneller, goedkoper en paradoxaal genoeg zelfverzekerder, omdat hij zich moest vastleggen op een conclusie.

De backend vervangbaar houden

Ik wilde het systeem niet vastleggen aan één specifieke modelprovider. Ik gebruik verschillende engines, afhankelijk van de taak. Soms Claude Code, soms Grok Build, of wat op dat moment het goedkoopst is. Om de kernlogica provider-agnostisch te houden, heb ik het werk opgesplitst in twee fasen.

Fase één is exploratie. De coding agent, die elk krachtig model kan zijn, leest de repo map, gebruikt de tools en genereert een ruw markdown-rapport. Dit is het kostbare denkwerk.

Fase twee is structurering. Een goedkope, snelle LLM neemt die markdown en formatteert deze om naar het strikte Pydantic-model. Deze fase vereist bijna geen redenering. Het is puur extractie en formattering, waardoor het op lichte hardware kan draaien.

Omdat de scheidslijn helder is, kan ik de backend vervangen zonder de validatielogica aan te raken. Het markdown-rapport fungeert als een universele adapter tussen het verkennende brein en de gestructureerde output die ik daadwerkelijk gebruik.

Wat echt werkte

Deze opzet heeft de manier waarop ik met binnenkomende issues omga veranderd. De classificatielaag sorteert nog steeds bugs van feature requests, maar nu neemt de analyselaag het direct daarna over. Tegen de tijd dat ik mijn editor open, heb ik al een bestandspad, een regelbereik en een voorgestelde wijziging klaarliggen. Ik controleer nog steeds alles handmatig. Dit is assistentie, geen autopilot. Maar het verzamelen van context dat vroeger