Skip to content

Commit dcccf6e

Browse files
authored
781 blogpost over tools in the loop (#799)
* wip * draft version * fix feedback
1 parent d8a3eba commit dcccf6e

2 files changed

Lines changed: 258 additions & 0 deletions

File tree

291 KB
Loading

blog/draft/tools-in-the-loop.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
---
2+
draft: true
3+
authors: [dimitri-van-hees]
4+
tags:
5+
- ai
6+
- llm
7+
- cli
8+
- validator
9+
- oas
10+
- adr
11+
- publiccode
12+
- open-source
13+
- standaarden
14+
description: >
15+
Voor wie AI inzet om overheidssoftware te bouwen, houden we naast de mens ook
16+
de tools in de loop: generators die het zware werk doen en validators die de
17+
regels bewaken. Zo verschuift het naleven van standaarden van menselijke
18+
oplettendheid naar deterministische tooling die je kunt vertrouwen.
19+
image: ./img/tools-in-the-loop.png
20+
---
21+
22+
# Tools in the loop: "human in the loop" krijgt hulp
23+
24+
![Abstracte weergave van het proces](./img/tools-in-the-loop.png)
25+
26+
"Human in the loop" is inmiddels het standaardantwoord op bijna elke zorg rond
27+
AI. Maar voor wie AI inzet om overheidssoftware te bouwen, is het verstandig om
28+
naast de mens ook _tools_ in de loop houden: generators die het zware werk doen
29+
en validators die de regels bewaken. Zo verschuift het naleven van standaarden
30+
van de oplettendheid van een mens en de welwillendheid van AI naar tooling die
31+
je kunt vertrouwen. Hoe dat samenwerkt, en aan welk arsenaal aan skills,
32+
generators, validators en andere tools we werken, lees je in deze post.
33+
34+
<!-- truncate -->
35+
36+
:::success[TL;DR]
37+
38+
Als je AI gebruikt om software te bouwen, houd dan naast de mens ook onze
39+
_tools_ in de loop:
40+
41+
- **Generators** doen het zware, repetitieve werk (boilerplate,
42+
projectstructuur) en zijn deterministisch.
43+
- **Validators** beantwoorden de waarheidsvraag "Voldoet dit aan de regels?".
44+
Niet het model, maar een tool met een vaste set regels.
45+
- De **command line** is de natuurlijke interface voor agents: de agent itereert
46+
op exit codes tot de checker `valid` teruggeeft.
47+
- AI is zo een hulpmiddel voor de input, niet het orakel dat de waarheid
48+
bepaalt.
49+
50+
Dit valt of staat met **standaarden**: elke afspraak is een stukje waarheid dat
51+
je in betrouwbare tooling stopt zodat AI het niet zelf hoeft te verzinnen.
52+
53+
:::
54+
55+
## Validators en generators worden steeds belangrijker
56+
57+
Je zou kunnen denken dat in een wereld waarin een AI-agent "gewoon de code
58+
schrijft" de behoefte aan generators en validators afneemt. Het
59+
tegenovergestelde is waar. Juist omdat een taalmodel plausibel-ogend werk
60+
produceert dat tóch fout kan zijn, wordt het werk dat je níet aan het model wilt
61+
overlaten belangrijker dan ooit.
62+
63+
Dat werk bestaat uit twee soorten. Het zware, repetitieve werk, zoals het
64+
genereren van boilerplates en het opzetten van een projectstructuur, dat kun je
65+
een generator laten doen. Die is deterministisch en doet elke keer hetzelfde. En
66+
de waarheidsvraag, "Voldoet dit aan de regels die wij hanteren?", kun je door
67+
een validator laten beantwoorden. Niet AI, niet de mens, maar een tool met een
68+
vaste set regels.
69+
70+
Bovendien hoeft AI zo minder zelf te "bedenken". Dat scheelt hallucinaties en
71+
het verbrandt geen onnodige tokens. Het model doet waar het goed in is, namelijk
72+
taal en intentie interpreteren, en de tools doen waar zij goed in zijn.
73+
74+
## CLI als natuurlijke interface voor AI-agents
75+
76+
Agents leven op de command line. Ze roepen tools aan, lezen de output, en
77+
bepalen op basis daarvan hun volgende stap. Dat maakt een CLI de meest
78+
natuurlijke interface die je een agent kunt aanbieden: deterministisch,
79+
scriptbaar, aan elkaar te knopen, en met een exit code en gestructureerde output
80+
waar een agent direct op kan itereren.
81+
82+
Daarom hebben onze tools sinds kort allemaal een command line interface
83+
gekregen, van de generators tot de checkers. Een invalid output uit onze checker
84+
is daarmee een exit status: de agent leest het, ziet wat er mis is, past het aan
85+
en draait de checker opnieuw. Daar draait de hele validatieloop op, zonder dat
86+
er een mens tussen hoeft te zitten.
87+
88+
## Hoe alles samenwerkt
89+
90+
Vanuit developer.overheid.nl bieden we de volgende features (deels al, deels
91+
binnenkort) aan. De rolverdeling:
92+
93+
- **Schema Register.** Een register van herbruikbare JSON schema's waar straks
94+
niet alleen mensen, maar ook agents uit kunnen putten. In plaats van schema's
95+
te verzinnen, verwijst de agent naar wat er al is. Met de komende upgrade naar
96+
[OpenAPI 3.1](/blog/2025/07/10/openapi-31-in-zicht) zijn deze schema's direct
97+
te gebruiken in OAS-documenten. Dit register is momenteel in ontwikkeling; we
98+
verwachten dit snel te kunnen lanceren.
99+
- **[Agent Skills](https://github.com/developer-overheid-nl/skills-marketplace).**
100+
Hiermee geven we agents instructies mee: welke tool, op welk moment, in welke
101+
volgorde. De skill is wat de agent dwingt om onze tooling te gebruiken in
102+
plaats van zelf te improviseren. Deze zijn in beta en nog volop in onderzoek,
103+
dus gebruiken op eigen risico! Eerder schreven we al over
104+
[hoe je standaarden in je AI-assistant laadt](/blog/2026/03/25/skills).
105+
- **[OAS Generator](https://developer-overheid-nl.github.io/oas-generator).**
106+
Genereert een boilerplate OpenAPI-document op basis van een `input.json`. Die
107+
boilerplate is al ADR-conform van opzet, dus de agent begint niet van scratch
108+
maar met een correct startpunt.
109+
- **[Checker](https://developer-overheid-nl.github.io/don-checker).** Onze
110+
linter/validator die een document toetst aan een ruleset, bijvoorbeeld de
111+
ADR-ruleset voor een OAS of de publiccode-ruleset voor
112+
[`publiccode.yml`](/kennisbank/open-source/standaarden/publiccode-yml). Bij
113+
`valid` mag de pijplijn door, bij `invalid` moet er opnieuw geïtereerd worden.
114+
Dit is de spil waar de hele kwaliteitsborging om draait.
115+
- **[Codegen Templates](https://github.com/developer-overheid-nl/codegen-templates).**
116+
Eigen [OpenAPI Generator](https://openapi-generator.tech/) templates, zodat de
117+
gegenereerde servercode voor API's aansluit op de API Design Rules en andere
118+
overheidsstandaarden. Momenteel hebben we een aantal smaken in de aanbieding,
119+
waaronder voor Java, Go, Node.js, Rust en Python.
120+
- **[Repo Docs Generator](/kennisbank/open-source/tutorials/tutorial-repo-docs-generator).**
121+
Genereert de standaard repo-documentatie: een `README.md`, `CONTRIBUTING.md`,
122+
`CODE_OF_CONDUCT.md`, `LICENSE`, `SECURITY.md`, `CHANGELOG.md` en een
123+
`publiccode.yml`. In één keer nette, consistente templates in plaats van
124+
handmatig samengeraapte bestanden.
125+
126+
De AI doet in dit geheel maar twee dingen: de `input.json` vullen, een vast
127+
formaat dat het model kent, en via dialoog met de gebruiker die input compleet
128+
maken. Pas als de input volledig is, wordt er daadwerkelijk gegenereerd.
129+
130+
## Generator en checker zijn complementair
131+
132+
Een terechte vraag is: als de generator al een boilerplate maakt conform de
133+
[API Design Rules (ADR)](/kennisbank/api-ontwikkeling/standaarden/api-design-rules),
134+
en de agent borduurt voort op wat er al staat, heb je die checker dan überhaupt
135+
nog nodig?
136+
137+
Het antwoord is ja, en het waarom is meteen het sterkste argument vóór deze
138+
opzet. Het klopt dat een agent geneigd is om voort te borduren op een bestaand,
139+
intern consistent document. Een schone boilerplate werkt als voorbeeld: de agent
140+
ziet hoe wij naar het register verwijzen, hoe we fouten modelleren, welke naming
141+
we hanteren, en trekt dat door. Dat is precies waarom je met een goede
142+
boilerplate begint. Het vernauwt de output, scheelt tokens en verkleint de kans
143+
op afwijkingen.
144+
145+
Maar het is geen garantie. Naarmate een document groeit, valt de oorspronkelijke
146+
boilerplate buiten het effectieve aandachtsvenster van het model. Voeg je
147+
functionaliteit toe waar geen voorbeeld voor in het document staat, dan valt het
148+
model terug op zijn trainingsdata, en die is niet ADR-conform. En over meerdere
149+
bewerkingen heen kunnen kleine afwijkingen zich opstapelen.
150+
151+
Daarom zijn de generator en de checker geen overlap maar complementair. De
152+
generator-boilerplate zorgt dat de checker bijna altijd meteen `valid`
153+
teruggeeft. De checker is er voor de keren dat dat niet zo is, of als er na de
154+
generatie nog wijzigingen aan de OAS doorgevoerd worden. Denk aan extra
155+
endpoints, filters, etc. De checker handhaaft de harde grens die een taalmodel
156+
statistisch nooit kan garanderen.
157+
158+
## Een overheids-API bouwen
159+
160+
Tijd om te laten zien hoe die loop er in de praktijk uitziet. De onderstaande
161+
flowchart toont het hele proces in één oogopslag; daaronder lopen we de stappen
162+
langs.
163+
164+
```mermaid
165+
graph TD
166+
A([''Bouw een overheids-API''])-->SK[/Agent Skill/]-->B[Agent verzamelt input]
167+
U[/User input/]<-->|Feedback|B
168+
B<-->|API Search|T1[(Schema Register)]
169+
B-->IN[/input.json/]-->C[[OAS Generator]]-->D[/openapi.json/]-->E[[Checker]]
170+
ADR[/ADR Ruleset/]-->E
171+
E-->|Invalid?|FIX[Agent fixt openapi.json]-->E
172+
E-->|Valid?|F[[OpenAPI Generator]]-->G[/Servercode/]
173+
CG[/Codegen Template/]-->F
174+
```
175+
176+
De gebruiker geeft de prompt "bouw een overheids-API". De juiste skill wordt
177+
getriggerd en stuurt de agent door een vast proces. Eerst verzamelt de agent
178+
input: deels door vragen te stellen aan de gebruiker, deels door het
179+
schema-register te doorzoeken naar bruikbare, herbruikbare schema's. Het
180+
resultaat is een complete `input.json`.
181+
182+
Die input gaat de OAS Generator in, die er een boilerplate `openapi.json` van
183+
maakt. Vervolgens komt de Checker om de hoek kijken. Deze toetst het document
184+
tegen de ADR-ruleset. Is het `invalid`, dan gaat het terug: de agent fixt de OAS
185+
en draait de checker opnieuw, net zo lang tot het klopt. Óók als het document na
186+
de generatie nog gewijzigd wordt dus.
187+
188+
Het belangrijkste aan dit plaatje is de lus rond de checker. De agent _kan_ niet
189+
langs de regels. Hij mag itereren, hij mag fouten maken, maar hij komt pas
190+
verder als een deterministische tool groen licht geeft. De waarheid zit niet in
191+
het model, maar in de checker.
192+
193+
## De code open source maken
194+
195+
Precies hetzelfde patroon keert terug voor een ander prompt. De flowchart
196+
hieronder laat zien hoe:
197+
198+
```mermaid
199+
graph TD
200+
H([''Maak dit open source''])-->AS[/Agent Skill/]-->I[Agent verzamelt input]
201+
U[/User input/]<-->|Feedback|I
202+
I-->T[[Repo Docs Generator]]
203+
T-->R[/README.md/]---C[/CONTRIBUTING.md, etc./]
204+
T-->P[/publiccode.yml/]-->L[[Checker]]
205+
PR[/Publiccode Ruleset/]-->L
206+
L--Invalid?-->M[Agent fixt publiccode.yml]-->L
207+
```
208+
209+
"Maak dit open source" trapt een vergelijkbaar proces af: de juiste skill wordt
210+
getriggerd, de agent verzamelt input en laat dat door de Repo Docs Generator
211+
lopen. Die genereert in één keer de complete set repo-documentatie, van
212+
`README.md` en `CONTRIBUTING.md` tot `CODE_OF_CONDUCT.md`, `LICENSE.md`,
213+
`SECURITY.md`, `CHANGELOG.md` en een `publiccode.yml`. Vervolgens komt dezelfde
214+
checker terug, nu met de publiccode-ruleset, die de `publiccode.yml` toetst. Is
215+
het `invalid`, dan fixt de agent het bestand en draait de checker opnieuw, exact
216+
dezelfde lus als bij het bouwen van de API. Saillant detail: als er reeds een
217+
`README.md` is, zoals het geval is nadat je de OpenAPI-generator hebt gebruikt,
218+
zal de agent deze aanpassen conform de template van de generator, welke de best
219+
practices voor een `README.md` bevat.
220+
221+
In het geval van een bestaande codebase, instrueert de skill de agent om te
222+
kijken naar de git remote, bestanden als `openapi.json` en het projectmanifest
223+
(zoals een `package.json`, `pyproject.toml` of `pom.xml`) om daar de benodigde
224+
input uit te halen. Doe je dit prompt vanuit de bestaande context, dan weet de
225+
agent nog dingen uit de eerdere input. Denk hierbij bijvoorbeeld aan de
226+
contactgegevens uit de zojuist gegenereerde OAS.
227+
228+
## Standaarden
229+
230+
Er zit een randvoorwaarde onder dit hele verhaal, en die verdient het om
231+
expliciet genoemd te worden: standaarden. De templates, generators en validators
232+
uit deze blog bestaan alleen omdat er standaarden onder liggen waar we ze
233+
tegenaan kunnen bouwen, de ADR, de publiccode-standaard, herbruikbare schema's.
234+
Zonder een vaste set regels is er niets om een boilerplate op te baseren of een
235+
document tegenaan te toetsen.
236+
237+
Hoe meer er gestandaardiseerd wordt, hoe nauwkeuriger we onze templates,
238+
generators en validators kunnen maken. Elke afspraak die we vastleggen is een
239+
stukje waarheid dat we uit het model kunnen halen en in deterministische tooling
240+
kunnen stoppen. Standaardisatie is de fundering die betrouwbaar bouwen met AI
241+
mogelijk maakt. Hoe steviger die fundering, hoe meer je met een gerust hart aan
242+
de tools kunt overlaten.
243+
244+
## Conclusie
245+
246+
Het resultaat is een proces dat reproduceerbaar en controleerbaar is. Dezelfde
247+
input levert dezelfde output, en wat eruit komt voldoet aantoonbaar aan onze
248+
regels, niet omdat een model toevallig goed gemutst was of een reviewer scherp
249+
oplette, maar omdat een tool het heeft afgedwongen.
250+
251+
De rolverdeling is daarmee helder. Het taalmodel is de orkestrator die intentie
252+
vertaalt naar input en tools aanroept, niet het orakel dat de waarheid bepaalt.
253+
Generators doen het zware werk, validators bewaken de grenzen. En de mens blijft
254+
gewoon in de loop, maar op het niveau waar menselijk oordeel telt: keuzes,
255+
context, akkoord. Niet op het naleven van regels die een machine beter onthoudt.
256+
257+
Of je AI inzet is aan jou. Maar áls je het doet, houd dan niet alleen de mens in
258+
de loop, maar óók beschikbare tools.

0 commit comments

Comments
 (0)