Terug naar artikelen

Week 22: Het systeem achter het systeem

Een week van onzichtbaar werk: architectuurdiagrammen van de complete podcast pipeline, Semgrep code-kwaliteitsborging, en het opschonen van content en vector stores.

Joop Snijder

Joop Snijder

Head of AI bij Info Support

Er zijn weken in dit experiment die je niet kunt laten zien aan een gebruiker. Geen nieuwe knop, geen fancy feature, geen AI-experiment dat je kunt demonstreren in een screenshot. Maar er is wel degelijk iets gebouwd — het systeem dat het systeem in stand houdt.

Dit was zo’n week.

Architectuur tekenen die al bestaat

De AIToday Live podcast pipeline is in twee jaar tijd organisch gegroeid. Scripts die scripts aanroepen, AI-processen die data doorgeven aan andere processen, vector stores, dashboards, deployment pipelines. Ik wist hoe het werkte, maar had het nooit goed vastgelegd.

Dat veranderde donderdag, toen ik besloot om de volledige architectuur te visualiseren in een set van 9 interactieve diagrammen. Niet als documentatie voor een klant of voor een opdrachtgever, maar gewoon: om het zelf te begrijpen. Om te zien of de logica klopte die ik in mijn hoofd had.

Wat me opviel tijdens dat werk: de pipeline bevat 27 afzonderlijke AI-toepassingen en meer dan 20 scripts. Dat klinkt overweldigend, maar in de diagrammen werd het ineens overzichtelijk. Elke fase — van opname tot publicatie — had zijn eigen verantwoordelijkheid. De A0-poster die ik aan het einde maakte, werkt als een periodiek systeem van de podcast: alle elementen gerangschikt per fase, per type, per rol.

Het werkt ook goed als indruk bij gasten.

Code die zijn eigen grenzen bewaakt

Als een codebase groeit, groeit ook het risico dat je per ongeluk door architectuurgrenzen heen loopt. Een import hier, een directe database-aanroep daar — elk afzonderlijk onschuldig, maar samen maak je de code brozer.

Maandag begon ik aan een set Semgrep-regels die dat moeten voorkomen. Vijf custom rules, elk gericht op een specifiek patroon in het Podcast2Socials project:

  • Elke AI-prompt moet via de EngineeredPrompt gateway lopen
  • Environment variables mogen geen hardcoded fallback weglaten
  • Modules mogen elkaars grenzen niet overschrijden
  • File storage moet via decorators
  • Hardcoded paden zijn verboden

Dat klinkt streng. En dat is ook de bedoeling. Maar wat me tegenviel: er bleken 45 bestaande code violations te zijn. Niet omdat de code slecht was geschreven, maar omdat de regels er simpelweg nog niet waren. Dus eerst baseline vastleggen, dan systematisch opruimen, daarna blocking mode inschakelen.

Het is architectuur-handhaving in drie fasen: benoemen, herstellen, borgen.

Twee systemen worden één

Ergens tijdens de groei van de pipeline hadden twee vector store-implementaties naast elkaar bestaan: de originele OpenAI RAG en een lokale Ollama variant. Beide werkten, beide werden bijgehouden, maar dat was onnodig complex.

Vrijdag was de beslissing: Ollama wint. De OpenAI RAG wordt volledig vervangen. Niet omdat OpenAI slechter is, maar omdat lokaal draaien bij mijn workflow past en ik niet twee systemen wil onderhouden die hetzelfde doen.

Die beslissing werd concreet omdat ik toch al bezig was met de podcast-aflevering S08E55. Een fragment dat ik had opgenomen moest worden verwijderd — bedrijfsgevoelig — en dat betekende chirurgisch werk: 13 SRT-entries aanpassen, 6 tekstbestanden opschonen, de afleveringsduur bijwerken, en alle referenties uit de vector store verwijderen. Terwijl ik toch in die database zat, leek het een goed moment om de architectuur te versimpelen.

Soms is opruimen een bijvangst van ander werk.

Kwaliteit die je pas opmerkt als het ontbreekt

Parallel aan dit alles liep het werk aan test coverage en mutation testing. Coverage was gestegen van een magere 12% naar 33%. Dat klinkt klein, maar het vertegenwoordigt een fundamentele verschuiving: van “we testen eigenlijk niets” naar “we hebben een baseline waarop we kunnen bouwen”.

Mutation testing leerde me dat sommige modules een plafond hebben. Je kunt 100% van de code afdekken met tests, maar als de tests niet controleren of de juiste logica draait, zegt die 100% niets. De mutation score — hoe goed tests fouten detecteren — bleef steken op 30% voor sommige modules. Dat is niet falen, dat is het systeem dat je vertelt waar de grenzen liggen.

Die conclusie ligt nu vast in een Architecture Decision Record.

Wat het met mij deed

Weken als deze zijn moeilijk te verdedigen. Als iemand vraagt “wat heb je gebouwd?”, heb ik geen demo klaarstaan. Geen nieuwe feature om te tonen. Maar het experiment is niet alleen over bouwen — het gaat ook over het professioneel houden van wat je bouwt.

Architectuurdiagrammen maken terwijl je het systeem al kent voelt overbodig, tot je ziet dat de diagrammen dingen laten zien die je dacht te weten maar niet had geformaliseerd. Semgrep-regels schrijven voelt bureaucratisch, tot je beseft dat je daarmee voorkomt dat je over twee maanden een uur kwijt bent aan een bug die een duidelijke import-grens had kunnen blokkeren.

Het is het verschil tussen code die werkt en code die werkt op een manier die je later nog kunt begrijpen.

Dit experiment gaat ook over dat verschil.

Het patroon

Als ik terugkijk op deze week, zie ik één overkoepelend thema: expliciet maken wat impliciet was. De architectuur die in mijn hoofd zat, nu in diagrammen. De coding standaarden die ik vanzelfsprekend vond, nu in Semgrep-regels. De twee vector stores die ik “gewoon wist” dat bestonden, nu versimpeld tot één.

Impliciet werkt zolang jij er bent. Expliciet werkt ook als je het een week later opnieuw bekijkt.

Head of Research Center AI bij Info Support. Ik schrijf over AI-strategie, AI-agents en de praktische implementatie van AI in organisaties.