Hoe je autonome AI-agenten een open vraagbereik geeft over bedrijfsdata, zonder de controle over rechten, herkomst, kosten en risico op te geven — en hoe je dat zo bouwt dat het blijft werken wanneer de modellen erachter onherkenbaar veel capabeler zijn geworden.
Organisaties willen AI-agenten die vragen over hun eigen data beantwoorden. De gangbare implementaties kiezen tussen twee kwaden: ofwel beperk je wat gevraagd mag worden (een vaste catalogus tools of rapporten — veilig maar dom), ofwel geef je het model vrije toegang (schema plus SQL-generatie — slim maar onbestuurbaar). Deze architectuur weigert die keuze.
De kern is een gateway: één doorgang tussen redeneerders en data, waar rechten, tenant-afbakening, volume, herkomst en kosten worden afgedwongen — niet door instructies aan het model, maar door code die draait ongeacht wat het model probeert. Daarboven staat een semantische laag die vastlegt welke entiteiten, velden, relaties en gecertificeerde metrieken bestaan, elk met een gevoeligheidsklasse. De agent stelt binnen die laag vrij zijn eigen bevragingen samen — ook vragen die niemand vooraf bedacht heeft — terwijl hij nooit een SQL-string aanraakt en zijn eigen afbakening niet kan uitbreiden.
De meeste mislukte AI-datatoegangprojecten mislukken niet in de bouw maar in de probleemstelling. "Bouw een chatbot op onze data" is een opdracht die het antwoord al verkeerd stuurt.
Hoe geef je een niet-deterministische redeneerder een open vraagbereik over data die meervoudig bestuurd is — per entiteit, per rol, per gevoeligheidsklasse, per rechtsgebied — zonder dat elke nieuwe vraag opnieuw een veiligheidsvraag wordt?
De laatste bijzin is de hele opgave. In een systeem met vaste rapporten is elk rapport één keer beoordeeld en daarna veilig. In een systeem met een open vraagbereik bestaat "de vraag" nog niet op het moment dat je hem moet goedkeuren. Je kan dus niet vragen beoordelen; je moet toegang beoordelen. Alles in deze architectuur volgt uit die verschuiving.
Je kan de vragen niet opsommen — de nuttige zijn per definitie de niet-voorziene. Je kan de data wél opsommen, en wie er wat van mag zien. Bevries daarom het bestuurbare en laat het onbestuurbare vrij.
Het model dat je vandaag kiest is over achttien maanden achterhaald, mogelijk van een andere leverancier, mogelijk lokaal draaiend om soevereiniteitsredenen. Alles wat governance is, moet daarbuiten staan — anders herbouw je het bij elke wissel.
Een traag antwoord is hinderlijk. Een overtuigend fout antwoord op een schadereserve, een marge of een blootstelling stuurt een verkeerde beslissing en wordt pas veel later ontdekt. Elk compromis valt daarom uit in het voordeel van controleerbaarheid.
In een gereguleerde omgeving is "waarom zei het systeem dit?" geen debugvraag maar een toezichtvraag, met termijnen en bewaarplichten. Bewijsvoering hoort in de architectuur, niet in de logging-backlog.
Dit is de analytische ruggengraat van het document. Elke controle in elk AI-systeem valt in één van drie klassen, en die klasse voorspelt hoe de controle zich gedraagt als het model beter wordt.
Wat: instructies in de systeemprompt. "Toon nooit gegevens van andere klanten." "Verzin geen cijfers." "Vraag om bevestiging vóór je iets wijzigt."
Waarom het faalt als grens: de werking hangt af van de bereidheid en het begrip van het model. Ze is niet af te dwingen, niet te bewijzen en niet uitputtend te testen — de ruimte van formuleringen die haar omzeilen is oneindig. Erger: een capabeler model vindt méér paden, niet minder, en tekst uit de data zelf (een klantnaam, een e-mailtekst, een schadedossier) kan met dezelfde autoriteit spreken als jouw instructie.
Legitiem gebruik: kwaliteit, toon, formaat, voorkeursvolgorde. Nooit: vertrouwelijkheid, afbakening, autorisatie, onomkeerbare handelingen.
Wat: beperken wat überhaupt geprobeerd kán worden. Een vaste catalogus van tien tools. Vooraf geschreven rapporten. Geen SQL-toegang.
Waarom het onvoldoende is: het werkt — maar het plafond ligt bij de verbeeldingskracht van de ontwerper op de dag dat hij de catalogus schreef. Naarmate modellen capabeler worden, wordt de restrictie de bindende beperking in plaats van het model. Je betaalt voor een redeneerder en gebruikt hem als menukaart.
Legitiem gebruik: kosten, prestaties, blast radius van handelingen. Ongeschikt als: primaire veiligheidsgrens, omdat elke uitbreiding opnieuw een veiligheidsbeoordeling vraagt.
Wat: controle die buiten het model draait en niet afhangt van zijn medewerking. Policy-evaluatie per veld. Afbakening die in de query geïnjecteerd wordt. Toelatingscontrole op volume. Read-only databaserollen. Verplichte herkomstvastlegging.
Waarom het standhoudt: de effectiviteit is onafhankelijk van wie of wat de aanvraag doet. Een kluisdeur vraagt niet hoe slim de persoon ervoor is. Dezelfde controle werkt identiek voor een zwak model, een superieur model, een gecompromitteerde integratie of een medewerker met gestolen inloggegevens — en dat is precies de eigenschap die je in een bedrijfsomgeving nodig hebt.
Kosten: ontwerpwerk vooraf. Je moet je datamodel semantisch beschrijven en classificeren vóórdat je AI erop loslaat. Dat is de investering die dit document verdedigt.
Drie gevestigde principes vormen de lakmoesproef voor elke toegangsarchitectuur. Dit ontwerp verhoudt zich er als volgt toe — inclusief de plek waar het bewust van de zuivere leer afwijkt.
Elke bevraging wordt op het moment zelf volledig geverifieerd: identiteit uit de sessie, policy per veld, afbakening opnieuw geïnjecteerd. De gateway is het policy enforcement point, de bestuurslaag het policy decision point. Verder dan klassiek Zero Trust: ook de redeneerder zelf is onvertrouwd — het ontwerp neemt aan dat het model gemanipuleerd kan zijn (injectie via data), vandaar geen tekstpad naar de opslag en afbakening buiten zijn bereik. "Intentie is geen toegangsprimitief" is never trust, always verify, toegepast op bedoelingen.
Het niet-vervalsbare zit erin: de afbakeningscontext bereikt de uitvoering buiten elk schema om, zodat de agent niet eens kán uitdrukken wat hem niet gegeven is; elke agent krijgt alleen het toolsubset van zijn rol; delegatie met vervaldatum is een klassieke capability-grant. Rondgereikte ondertekende tokens ontbreken bewust: binnen één servergrens met één reference monitor voegen ze niets toe. Zodra er servicegrenzen komen (de federatieve uitvoering, §3.3), materialiseren beslissingen wél als kortlevende ondertekende query-capabilities — zelfde model, gedistribueerde vorm.
Zuiver PoLP per operatie×veld is bij open bevraging het duizenden-beslissingen-probleem — en onbeheerbare rechtenlijsten verzanden in verouderde grants: privilege sprawl schendt least privilege harder dan een grovere maar onderhouden structuur. Hier ontstaat de minimale bevoegdheid per aanvraag als doorsnede: rol×klasse ∩ subjectreikwijdte ∩ resource-verfijning ∩ verplichtingen (maskering, alleen-geaggregeerd, geen export) ∩ doelbinding ∩ toolsubset ∩ aflopende delegaties. Het minimale-pad-gedrag (eerst namen, dan één nummer) is dynamisch least privilege — minimalisatie per vraag, wat statische rechten per definitie niet kunnen.
Rollen encoderen in dit ontwerp geen intenties maar functienoodzaak (need-to-know); ze zijn een administratieve compressie van grants. De handhaving verwijst nergens naar bedoelingen.
De vraag "werkt dit nog over drie jaar, als AI bovenmenselijk is geworden?" is beantwoordbaar, en het antwoord is niet "we hopen het".
Definitie. Een controle is capaciteitsonafhankelijk wanneer haar effectiviteit niet afhangt van het vermogen van de entiteit die ze beheerst.
Toegangscontrole op een database is capaciteitsonafhankelijk: ze kent geen verschil tussen een junior analist en een superintelligentie, ze kent alleen legitimatie. Een instructie in een prompt is dat niet: haar werking is volledig een functie van hoe het model haar interpreteert.
Een architectuur houdt stand bij stijgende modelcapaciteit als, en alleen als, groeiende capaciteit de waarde verhoogt zonder de veiligheid te verlagen. Dat vraagt twee dingen tegelijk:
Een beter model stelt betere vragen, kiest slimmere aggregaties, herkent scherper welke domeinkennis het nodig heeft en trekt betere conclusies uit weinig data. Al die winst valt binnen de vraagzijde — precies wat deze architectuur vrijlaat. Meer capaciteit betekent hier meteen meer waarde, zonder één regel code.
Policy-evaluatie, afbakeningsinjectie en toelatingscontrole draaien identiek, ongeacht wie vraagt. Ze worden niet zwakker doordat de aanvrager slimmer is. Meer capaciteit betekent hier géén extra risico — en dat is de enige reden waarom je een sterker model gerust kan inschakelen.
Een praktische investeringsgids die uit hetzelfde denken volgt. Als je vandaag budget verdeelt over een AI-programma, is dit de verdeling die over drie jaar nog verdedigbaar is:
| Depreciëert snel — houd dun en vervangbaar | Appreciëert — hier hoort de investering |
|---|---|
| Promptteksten en few-shot-voorbeelden | Ontologie en semantische laag — de vastgelegde betekenis van je entiteiten, velden en relaties |
| Modelkeuze, fine-tunes, leverancierspecifieke koppelingen | Gegevensclassificatie — wat is gevoelig, waarom, en onder welk regime |
| Toolimplementaties die om de eigenaardigheden van één model heen gebouwd zijn | Policy als data — wie mag wat, uitgedrukt zodat het evalueerbaar en testbaar is |
| Orkestratieframeworks van dit jaar | Gecertificeerde metriekdefinities — de ene, gezaghebbende berekening van marge, blootstelling, schaderatio |
| Retrieval-afstemming rond een specifiek embeddingmodel | Kennislaag en precedentenverzameling — hoe deze organisatie beslist, vastgelegd (§2.2) |
| Interface-details van de chatlaag | Bewijs- en evaluatieverzameling — traces, gouden vragen, regressiedekking |
Uitspraken die altijd gelden, ongeacht domein, model of implementatie. Wanneer een keuze in de bouw met een principe botst, is de keuze fout — niet het principe.
De scheiding die het systeem onderhoudbaar houdt. Elke laag heeft een eigen wijzigingsritme, een eigen eigenaar en een eigen kwaliteitsregime — en dat is geen esthetiek maar de reden dat een modelwissel de governance niet raakt.
Data zegt wat er gebeurd is. Kennis zegt wat het betekent. Een redeneerder die de eerste heeft en de tweede mist, produceert cijfers die kloppen en antwoorden die niet deugen.
| Tier | Inhoud | Laadmoment | Waarom deze laag bestaat |
|---|---|---|---|
| 0 · Register | Alle domeinen met trefwoorden, routes en een verwijzing naar hun kerndocument | Altijd, in elke aanroep (gecached) | De redeneerder weet wat er bestaat zonder iets ervan te kennen. Een paar duizend tokens vervangen honderdduizenden. |
| 1 · Kern | Doel van het domein, invarianten, veldbetekenis, statusverlopen, verboden | Voor de één tot drie gekozen domeinen | Voorkomt de meest voorkomende fout: correcte SQL op een verkeerd begrepen veld. Dit is waar "welke status telt als openstaand" thuishoort. |
| 2 · Regels | Bedrijfsregels, processtappen, randgevallen, uitzonderingen | Op aanvraag, per sectie | Onbegrensd in omvang zonder de contextkosten van elke vraag te verhogen. De redeneerder haalt op wat de vraag vereist. |
| 3 · Precedent | Uitgewerkte gevallen, eerdere beslissingen met motivering, interpretaties van toezichthouders, architectuurbesluiten | Op aanvraag, wanneer de vraag om oordeel vraagt | Institutioneel geheugen. Het verschil tussen een antwoord dat in het algemeen juist is en een antwoord dat consistent is met hoe deze organisatie beslist. |
Alle vier de tiers worden opgehaald via de gateway, niet via een bestandslezing naast de deur. Drie redenen, en de derde is de belangrijkste: kennisdocumenten kunnen zelf gevoelige informatie bevatten — een tier-3-precedent beschrijft een concreet dossier; toegang tot een domeinkerndocument verraadt dat het domein bestaat; en de vraag welke kennis geraadpleegd werd, is onderdeel van de verantwoording van het antwoord. Kennisophaling is dus rechtengecontroleerd en gelogd, net als elke andere aanvraag.
De bestuurslaag is het declaratieve geheugen van wat mag: alles wat hier staat is data — versiebeheerd, evalueerbaar, testbaar en te simuleren vóór inwerkingtreding. Ze wijzigt op het ritme van de organisatie (een nieuwe rol, een strengere regel, een tijdelijke delegatie), nooit op het ritme van de code. En ze doet zelf niets: de gateway (laag 3) dwingt af wat hier gedeclareerd is.
De vier blokken hierboven worden in deze volgorde uitgewerkt: het semantisch register (§2.3.A), de policy (§2.3.B), het handelingsregister (§2.3.C) en de routering (§2.3.D).
De samenhang in één zin: het register beschrijft, de policy verleent, het handelingsregister begrenst het doen, en de routering begrenst de denker. Wie iets aan het gedrag van het systeem wil veranderen, verandert hier data — en kan in de bewijslaag nalezen wat die verandering deed.
Het register is de afgesproken werkelijkheid: wat er bestaat voor de AI. Nadrukkelijk niet het fysieke schema, maar een bewuste, geclassificeerde doorsnede daarvan met betekenis eraan vast.
// Eén resource, declaratief. Domeinneutraal patroon;
// hier ingevuld voor een commerciële opportuniteit.
defineResource({
naam: "Opportuniteit", opslag: "leads", domein: "commercieel",
omschrijving: "Verkoopkans vóór promotie naar uitvoeringsproject.",
// VERPLICHT — geen resource zonder afbakeningspad. Lint faalt.
afbakening: { soort: "TENANT", pad: "tenants.some.tenantId" },
velden: {
id: { type: "id", klasse: "INTERN" },
naam: { type: "tekst", klasse: "INTERN", filterbaar: true },
status: { type: "enum", klasse: "INTERN", domeinwaarden: "LeadStatus" },
ontvangenOp: { type: "datum", klasse: "INTERN", filterbaar: true },
waarde: { type: "geld", klasse: "COMMERCIEEL", aggregeerbaar: true },
contactTel: { type: "tekst", klasse: "PERSOONSGEGEVEN",
maskering: "laatste4", grondslag: "gerechtvaardigd belang — contactopname" },
// Sleutels, tokens, ruwe documenten: staan hier NIET → bestaan niet voor de AI.
},
relaties: {
interacties: { naar: "Interactie", soort: "veel", telbaar: true },
conversaties: { naar: "Conversatie", soort: "veel", telbaar: true },
klant: { naar: "Organisatie", soort: "een" },
},
// Gezaghebbende berekeningen. De redeneerder mag ze gebruiken, niet herleiden.
metrieken: {
winratio: { klasse: "COMMERCIEEL", impl: canon.winratio,
definitie: "gewonnen / (gewonnen + verloren), excl. ingetrokken",
eigenaar: "Commercieel directeur", herzienOp: "2026-06-01" },
},
kwaliteit: { notitie: "Data vóór 2024 is gemigreerd; statussen zijn benaderd." },
limieten: { standaard: 50, max: 500 },
indexen: ["tenants.tenantId", "status", "ontvangenOp"],
})
Vijf tot zeven klassen volstaan voor vrijwel elke organisatie. Meer klassen geven schijnprecisie en onbeheersbare matrices; minder dwingt alles naar het strengste regime.
| Klasse | Aard | Standaardregime |
|---|---|---|
| Intern | Namen, referenties, statussen, datums | Alle geauthenticeerde interne rollen |
| Operationeel | Uitvoering, planning, voortgang, capaciteit | Rollen met uitvoerende verantwoordelijkheid |
| Commercieel | Prijzen, offertes, kansen, klantwaarde | Commerciële en leidinggevende rollen |
| Financieel | Bedragen, marges, kosten, blootstelling, reserves | Financiële rollen; afgebakend per juridische entiteit |
| Persoonsgegeven | Identificeerbare gegevens van natuurlijke personen | Beperkt, met maskering en doelbinding; grondslag vastgelegd per veld |
| Bijzonder | Gezondheid, biometrie, strafrechtelijk — AVG art. 9/10 | Alleen expliciete grondslag; vaak volledig uitgesloten voor AI-verwerking |
| Geheim | Sleutels, tokens, inloggegevens, ruwe documenten | Niemand. Staat niet in het register — bestaat niet |
genegeerd. Eén bewuste beslissing per migratie op een blootgestelde tabel; de rest van het schema blijft buiten schot. Whitelist = veiligheid, gratis en schemabreed; CI-check = volledigheid, gericht en goedkoop.De voor de hand liggende tegenwerping: een serieus datamodel telt duizenden kolommen — de reference implementation telt er ruim drieduizend over 174 tabellen — en die stuk voor stuk classificeren is onbegonnen werk. Terecht. Daarom werkt de classificatie met vier mechanismen die de last terugbrengen van duizenden regels naar tientallen beslissingen:
De veiligheid zit in de whitelist: niet-geregistreerd = onbereikbaar, schemabreed en gratis. De bouwstraatcontrole is enkel het drift-alarm daarbovenop en geldt uitsluitend voor kolommen van al blootgestelde tabellen (zie het kader in §2.3.A hierboven). Een eerste fase met vijf resources vraagt dus vijf besluiten, niet drieduizend.
Elke resource draagt één standaardklasse; alleen afwijkende velden krijgen een eigen regel. Een factuurtabel is standaard financieel, met het nummer als interne uitzondering en het ruwe documentveld als geheime. In de praktijk: één beslissing per tabel plus een handvol uitzonderingen — voor de reference implementation circa zestig tabelbesluiten in plaats van 3.500 veldregels.
De eerste vulling wordt gegenereerd — uit naamconventies, typen en de bestaande kennisdocumenten — en door een mens beoordeeld. Dit is ook hoe de industrie het doet: classificatietooling stelt automatisch voor, mensen bevestigen de twijfelgevallen. Een middag review in plaats van weken invoerwerk.
Organisaties met per-veld-documentatie — datadictionaries, AI-bewerkbaarheidstabellen, gegevenscatalogi — voegen één attribuut toe aan een bestaand ritueel, geen nieuw proces. De reference implementation onderhoudt zulke veldtabellen al voor zestig modules; de klasse is er één kolom bij.
Het register zegt wat er is. De policy zegt wie er wat mee mag. Bewust gescheiden: het register verandert met het datamodel, de policy met de organisatie — en ze hebben verschillende eigenaars en verschillende goedkeuringswegen.
Policy is data, geen code: evalueerbaar, testbaar, diffbaar, en te simuleren vóór inwerkingtreding. Standaard is weigeren. Beslissingen zijn niet binair maar drieledig.
rol COMMERCIEEL → lees:PERSOONSGEGEVEN → TOESTAAN, met doelbinding. Vanaf dat moment geldt dat voor élk veld van die klasse.
klasse + resource): nog steeds een handvol regels, geen veldwerk. Hetzelfde principe als beveiligingsclearances: wie SECRET mag lezen, mag alle SECRET-documenten lezen — niemand zet de clearance op elk document opnieuw.// Eén policyregel — de volledige vorm. Rechten worden verleend per (rol, actie,
// klasse), optioneel verfijnd per resource en per subjectbereik.
type PolicyRegel = {
rol: Rol // subject
actie: "lees" | "handel"
klasse: Gevoeligheidsklasse
resource?: ResourceNaam // verfijning: klasse+resource (leads wél, werknemers niet)
reikwijdte?: "eigen" | "team" | "organisatie" // subjectbereik binnen de geïnjecteerde afbakening;
// default "organisatie" — zet "eigen"/"team" waar
// portefeuilles persoonsgebonden zijn (§"Intentie")
effect: "TOESTAAN" | "WEIGEREN"
verplichtingen?: Verplichting[]
geldigTot?: Datum // delegatie/mandaat: aflopende verlening bij vervanging
verleendDoor?: GebruikerId // wie delegeerde — audit-spoor
}
type Beslissing = // uitkomst van policy-evaluatie per element
| { effect: "TOESTAAN" }
| { effect: "WEIGEREN"; reden: string; ontbrekendRecht: string }
| { effect: "TOESTAAN"; verplichtingen: Verplichting[] }
type Verplichting =
| { soort: "MASKEER"; patroon: "laatste4"|"domein"|"volledig" }
| { soort: "ALLEEN_GEAGGREGEERD"; minGroepsgrootte: number } // k-anonimiteit
| { soort: "MAX_RIJEN"; n: number }
| { soort: "GEEN_EXPORT" } // tonen mag, meenemen niet
| { soort: "MODEL_BEPERKING"; eisen: ModelEis } // zie hieronder
| { soort: "DOELBINDING"; toegestaneDoelen: string[]
defaultDoel?: string } // afgeleid/expliciet → trace (§"Doelbinding")
| { soort: "VIER_OGEN"; goedkeurderRol: string } // bij handelingen
Zonder verplichtingen wordt elk gevoelig veld een dichte deur en verschraalt het systeem tot triviale vragen. Met verplichtingen wordt het genuanceerd: een commerciële rol ziet bedragen geaggregeerd met een minimale groepsgrootte van vijf — zodat een groep van één de maskering niet omzeilt; een uitvoerende rol ziet contactgegevens gemaskeerd; een medewerker die een financiële vraag stelt krijgt geen leeg scherm maar de mededeling welk recht ontbreekt en bij wie het te halen is.
MODEL_BEPERKING is de meest onderschatte bouwsteen van deze architectuur. Omdat de policy weet welke klasse data een antwoord bevat, en de routeringslaag weet welke eigenschappen elke provider heeft, kan je uitdrukken: "persoonsgegevens mogen uitsluitend verwerkt worden door een provider met verwerkingslocatie in de EU, zonder training op invoer en met nulretentie; bijzondere categorieën uitsluitend door een model dat binnen ons eigen netwerk draait."
De verplichting DOELBINDING roept meteen de praktische vraag op: gebruikers zeggen zelden waarom ze iets nodig hebben. Het antwoord is dat het doel geen formulier is dat de gebruiker invult, maar een interpretatie die de agent maakt en vastlegt. Vier regels maken dat werkbaar én verdedigbaar:
Elke policyregel kan een defaultDoel dragen — voor een commerciële rol op contactgegevens is dat vanzelfsprekend contactopname, het standaarddoel van die functie. Routinevragen lopen daardoor frictieloos door; de trace markeert het doel als afgeleid of expliciet, zodat een auditor ziet wat interpretatie was en wat de gebruiker letterlijk zei.
De agent weigert nooit op een gegokt doel. Is de vraag eenduidig, dan leidt hij het doel af; is ze dat niet, dan stelt hij één korte wedervraag. Een weigering volgt uitsluitend wanneer het doel verklaard of evident verboden is. Een doelbindingsregime dat routinevragen onderbreekt wordt omzeild — en een omzeilde controle is erger dan geen.
Wie de eigenaar van een gevonden voorwerp zoekt, heeft geen dertig telefoonnummers nodig maar een namenlijst en daarna één nummer. Zodra het doel bekend is, kan de agent het minst gegevensintensieve antwoord voorstellen. Dataminimalisatie wordt zo geen blokkade maar een beter antwoord — iets dat noch botweg weigeren, noch alles dumpen ooit oplevert.
Ze blokkeert verklaard verboden doelen en legt elke claim vast — meer niet. Een gebruiker die liegt over zijn bedoeling houd je er niet mee tegen; wel is achteraf bewijsbaar wat werd geclaimd en wat werd verstrekt. De sloten heten whitelist, afbakening, verplichtingen en toelating; doelbinding is de verklaring-onder-logging daarbinnen.
eigen / team / organisatie. Een kleine organisatie kiest team-lezen (collega's vallen voor elkaar in); een strikte omgeving kiest eigen plus delegatie met vervaldatum: een leidinggevende verleent tijdelijk leesrecht op de portefeuille van de afwezige — expliciet, aflopend, gelogd. Dat is het mandaatmechanisme dat gereguleerde sectoren al kennen, uitgedrukt als policyregel.Het resourceregister beschrijft wat gelezen kan worden; het handelingsregister beschrijft wat gedaan kan worden: de volledige lijst van handelingen die een agent ooit mag voorstellen of uitvoeren, elk met een risicoprofiel. In een leesomgeving (autonomieladder t/m L2) blijft dit register leeg; het wordt ontworpen vóórdat de eerste handeling verleend wordt, nooit erna.
Een handeling is dus nooit "een bevraging met een schrijfvlag" (principe 9). Elke handeling staat vooraf gedeclareerd met haar risicoprofiel:
type Handeling = {
naam: string // bv. "herinnering.verstuur", "reserve.bijstel"
domein: string // koppelt aan kennislaag en resources
omkeerbaarheid: "OMKEERBAAR" // ongedaan te maken zonder spoor naar buiten
| "COMPENSEERBAAR" // herstelbaar met een tegenhandeling (creditnota)
| "ONOMKEERBAAR" // verzonden mail, externe melding, betaling
reikwijdte: { maxBedrag?: Geld; maxAantal?: number; perTijdvak?: Duur }
voorwaarden: Conditie[] // bv. "alleen op eigen portefeuille", "status = X"
minimumLadder: "L3" | "L4" | "L5" // laagste autonomieniveau waarop dit ooit mag
goedkeuring?: { rol: string; vierOgen?: boolean } // vereist bij L4
notificatie: Rol[] // wie het altijd te zien krijgt — de deur die lawaai maakt
terugdraaiplan?: string // verplicht bij L5: hoe de envelop-noodstop herstelt
}
Drie voorbeelden laten zien hoe het risicoprofiel de plaats op de ladder bepaalt — niet andersom:
| Handeling | Omkeerbaarheid | Typische verlening | Waarom |
|---|---|---|---|
| Interne taak aanmaken / afspraak verschuiven | Omkeerbaar | L5 — binnen envelop | Volledig intern herstelbaar; envelop begrenst aantal per dag; notificatie aan de betrokkene volstaat. |
| Betalingsherinnering versturen | Onomkeerbaar (extern zichtbaar) | L4 — na goedkeuring | Raakt een klantrelatie. Goedkeuring per stuk of per batch; reikwijdte begrenst het aantal per run. |
| Dossier-verantwoordelijke wijzigen / reserve bijstellen | Compenseerbaar, gevoelig | L4 met vier ogen | Precies de handeling uit het intentie-kader (§2.3.B): de dief moet door een deur die lawaai maakt — notificatie aan de oorspronkelijke verantwoordelijke is verplicht, niet optioneel. |
De gebruiker (rol FINANCIEEL) typt: "Stuur een betalingsherinnering naar iedereen die meer dan 30 dagen over vervaldatum zit."
De agent stelt via de gewone leeslaag vast om wie het gaat: 13 openstaande facturen, vervaldatum > 30 dagen verstreken. Dit deel is volledig open — geen register nodig, de vraag had ook heel anders kunnen luiden.
De agent vindt factuur.herinnering in het handelingsregister en toetst elke kandidaat aan de gedeclareerde voorwaarden. Eén factuur valt af: die klant kreeg vier dagen geleden al een herinnering, en de voorwaarde eist een cooldown van zeven dagen. Blijven over: 12 — binnen de reikwijdte (max. 15 per run). De agent meldt de uitgesloten klant expliciet, met reden.
Niets wordt verstuurd. De agent legt een voorstel voor: de lijst van 12, per klant het openstaande bedrag, dagen over vervaldatum en het gekozen mailtemplate. De gebruiker heeft rol FINANCIEEL — precies de goedkeurderrol uit het register — en keurt de batch met één klik goed (of haalt er klanten uit).
De uitvoering loopt via het bestaande mailpad van de applicatie — geen tweede schrijfroute. In de trace: de bevraging, de voorwaardentoets (incl. de uitgesloten klant), het voorstel, wie goedkeurde, en per mail het resultaat. De notificatie uit het register gaat naar de rol FINANCIEEL.
Merk op waar de intelligentie zat: in het vertalen van "iedereen die te ver over datum zit" naar de juiste selectie, het toepassen van de cooldown, en het opstellen van het voorstel. Het register bepaalde alleen de vangrails: wélke handeling bestaat, haar voorwaarden, en dat er een mens tussen zit. Had de gebruiker rol COMMERCIEEL gehad, dan was stap 3 geëindigd in een aanbeveling: "12 kandidaten gevonden — goedkeuring vereist rol FINANCIEEL."
De vierde component van de bestuurslaag is kort maar principieel: welk model wat mag doen is een bestuursbeslissing, geen implementatiekeuze. De mechaniek van modelrollen en adapters staat in §2.5.B; hier staat wat erover beslist wordt en door wie.
De routeringstabel is configuratie — per organisatie-eenheid, wijzigbaar zonder deploy, met versiehistoriek:
{
"routering": {
"LICHT": { "provider": "…", "model": "…", "maxTokens": 1024 },
"WERKER": { "provider": "…", "model": "…", "maxTokens": 4096 },
"FRONTIER": { "provider": "…", "model": "…", "maxTokens": 8192 },
"CRITICUS": { "provider": "…ander dan WERKER…" } // diversiteit is de waarde
},
"residentie": { // gekoppeld aan MODEL_BEPERKING (§2.3.B)
"PERSOONSGEGEVEN": { "verwerkingslocatie": "EU", "trainingOpInvoer": false, "retentieDagen": 0 },
"BIJZONDER": { "verwerkingslocatie": "ON_PREM" }
},
"escalatie": { "bijComplexiteit": {…}, "naGatewayFouten": 2, "maxEscalaties": 1 },
"budget": { "perGesprekEur": 0.50, "perDagEur": 25, "bijOverschrijding": "WEIGEREN" }
}
Vier beslissingen leven hier, elk met een eigenaar (§3.4): de rol-naar-model-toewijzing (AI-platformteam — dit is de knop waarmee een modelwissel een instelling is, principe 10); de residentie-eisen per gegevensklasse (privacy en security — de gateway dwingt ze af via de verplichting MODEL_BEPERKING: raakt een antwoord persoonsgegevens, dan vernauwt de toegestane providerverzameling automatisch); de escalatieregels (wanneer een zwaarder model gerechtvaardigd is — twee afgewezen bevragingen zijn goedkoper te escaleren dan vijf mislukte rondes); en de budgetten met hun overschrijdingsgedrag — weigeren, degraderen naar een goedkoper model, of doorlaten met melding; de keuze hoort bij de budgeteigenaar, niet bij de ontwikkelaar (§3.2).
De gateway is de enige doorgang tussen redeneerders en bronnen (principe 1) en het handhavingspunt van alles wat de bestuurslaag declareert. Zelf bevat ze géén beleid — ze voert het uit. Elke aanvraag, hoe klein ook, passeert hier; er bestaat geen tweede pad.
Drie onderdelen, in leesvolgorde:
Vier API-families (kennis, catalogus, bevraging, handeling) met zes aanroepen in de leesomgeving, en de negen-stappen-pijplijn die achter de bevragings-API draait — inclusief de mapping welke aanroep welke stappen doorloopt, en het dataflow-schema. §2.4.A
De declaratieve taal waarin de agent vraagt (geen SQL, geen tekstpad naar de opslag), wat bewust onuitdrukbaar is, en de drie vallen waar de compiler op getest moet zijn. §2.4.B
Elke weigering is een gestructureerd tegenvoorstel met uitvoerbare suggesties — het mechanisme dat de agent zelfcorrigerend maakt. §2.4.C
Zes vermogens in plaats van tientallen vragen. Dat is niet minder intelligentie maar een andere plaatsing ervan: een tool die een vraag is, is eindig; een tool die een vermogen is, is dat niet.
| API-familie | Aanroep | Doet | Levert | Wanneer |
|---|---|---|---|---|
| Kennis | kennis.register | Tier 0 — welke domeinen bestaan | Domeinregister, enkele duizenden tokens | Altijd, gecached |
| kennis.lees | Tier 1, 2 of 3 van een domein, of één sectie | Betekenis, regels of precedent | Zodra het domein bekend is | |
| Catalogus | catalogus.beschrijf | Registerdoorsnede voor genoemde resources | Velden, klassen, relaties, metrieken — geannoteerd met toegang | Vóór het samenstellen van een bevraging |
| Bevraging | bevraag.plan | Droogloop: valideren, autoriseren, ramen — zonder data | Toelaatbaarheid, geschat volume, waarschuwingen | Bij twijfel over omvang of rechten |
| bevraag.voer_uit | De bevraging lezend uitvoeren onder het volledige regime — dit is géén handeling | Rijen plus herkomstenvelop | De werkelijke datatoegang | |
| zoek | Hulpcall: vrije tekst → entiteitsidentificatie. Technisch een vooraf vastgelegde, begrensde bevraging | Maximaal tien kandidaten met referentie | Wanneer de vraag een entiteit bij naam noemt | |
| Handeling | handel.stel_voor · keur_goed · voer_uit · draai_terug | Bestaan niet in de leesomgeving (ladder t/m L2). Verschijnen pas wanneer L3+ verleend wordt, gestuurd door het handelingsregister (§2.3.C) | Vanaf autonomieniveau L3 | |
De negen stappen hieronder zijn de volledige pijplijn van de bevragings-API. De andere aanroepen zijn lichter en doorlopen een verkorte vorm — maar nooit nul: óók een kennisaanroep wordt geautoriseerd en vastgelegd (kennis is data, §2.2).
| Aanroep | Doorlopen stappen | Toelichting |
|---|---|---|
| kennis.register · kennis.lees | 1 · 2 · 9 | Binden (bestaat het domein/de sectie?), autoriseren (mag deze rol dit kennisdoc?), vastleggen. Geen raming — docs hebben een vaste, bekende omvang. |
| catalogus.beschrijf | 1 · 2 · 9 | De toegangsannotatie per veld in het antwoord ís stap 2, vooraf uitgevoerd voor de hele doorsnede. |
| bevraag.plan | 1 – 5 | Droogloop: stopt ná de toelating, vóór de uitvoering. Geen data, wel het oordeel en de raming. |
| bevraag.voer_uit | 1 – 9 | De volledige pijplijn. |
| zoek | 1 · 2 · 6 · 9 | Vaste, begrensde query (max. 10 kandidaten, alleen INTERN-velden) — raming en toelating zijn overbodig omdat de vorm vastligt. |
Elke bevraag.voer_uit doorloopt exact deze stappen. Geen uitzonderingen, geen interne route die er drie overslaat. De rood genummerde stappen zijn de handhavingspunten — klasse 3.
De redeneerder schrijft geen SQL. Hij schrijft een declaratieve specificatie die de gateway compileert. Dat verplaatst uitdrukkingskracht in plaats van haar in te perken: alles wat een bedrijfsvraag nodig heeft is uitdrukbaar, alles wat gevaarlijk is niet.
type Bevraging = {
van: ResourceNaam // uit het register
selecteer?: string[] // velden, ook via 1-op-1 paden
meet?: Meting[] // aggregaties over relaties of velden
waar?: Filter // boom: en/of/niet + veldpredicaten
groepeer?: string[]
sorteer?: { veld: string; richting: "op"|"af" }[]
limiet?: number // begrensd door registermaximum
doel?: string // doelbinding, verplicht bij persoonsgegevens
}
type Meting =
| { als: string; tel: RelatiePad; waar?: Filter } // telling over relatie
| { als: string; som: VeldPad; waar?: Filter } // mits aggregeerbaar
| { als: string; gem|min|max: VeldPad }
| { als: string; metriek: MetriekNaam } // GECERTIFICEERD
Alleen gedeclareerde relatiepaden, maximaal drie stappen diep. Geen kruisproducten, geen koppeling op velden die geen relatie zijn. Dit sluit zowel prestatieontsporingen als onbedoelde datacombinaties uit — dat laatste is een privacyrisico dat zelden benoemd wordt.
Er is geen veld waarin tekst de opslag bereikt. De compiler bouwt uit gevalideerde identifiers en geparametriseerde waarden. Injectie is geen risico dat beheerst wordt maar een constructie die niet bestaat — het antwoord op de vraag hoe je een API zo ontwerpt dat er niet ter plekke gevaarlijke query's ontstaan.
Velden die de basis vormen van een gecertificeerde metriek staan op aggregeerbaar: false. Een som erover wordt geweigerd met verwijzing naar de metriek. Zo kan de redeneerder geen eigen definitie van marge of blootstelling uitvinden.
Tenant-, entiteit- en rechtsgebiedsleutels zijn niet filterbaar en niet selecteerbaar. Ze bestaan uitsluitend als injectie. De redeneerder kan er niet naar vragen en er niet op filteren — en kan dus ook niet ontdekken wat hij niet mag zien.
Waar een naïeve implementatie stukloopt. Alle drie zijn echt en alle drie horen in de testverzameling van de compiler, niet in de oplettendheid van de gebruiker.
Tel je in dezelfde bevraging twee relaties met gewone koppelingen, dan vermenigvuldigen de rijen: een entiteit met tien interacties en vier berichten geeft veertig rijen en beide tellingen worden fout. Regel: elke telling of som over een relatie wordt een gecorreleerde subbevraging, nooit een koppeling in de hoofdbevraging.
"Sorteer op aantal interacties" dwingt volledige berekening vóór de limiet kan knippen. Op tweeduizend rijen prima, op twee miljoen niet. Regel: het register declareert bruikbare indexen; sorteren op een afgeleide is toegestaan tot een geraamde basiskardinaliteit, daarboven weigert de raming met de suggestie eerst te filteren.
De hoofdentiteit afbakenen volstaat niet. Telt de redeneerder over een relatie, dan moet ook die subbevraging afgebakend worden — anders tellen records buiten de afbakening mee. Een lek dat er als een gewoon getal uitziet, en daarom gevaarlijker dan een zichtbare fout. Regel: injectie loopt over het volledige relatiepad; verplichte test per resource dat een aanvraag van A geen record van B raakt.
Het onderdeel dat een star systeem van een lerend systeem scheidt. Een weigering is geen doodlopende weg maar een tegenvoorstel — en dat maakt de redeneerder zelfcorrigerend zonder dat iemand hem iets hoeft te leren.
{
"toegelaten": false,
"code": "VOLUME_OVERSCHREDEN",
"geschat": { "rijen": 2014, "tokens": 41200 },
"drempel": { "rijen": 500, "tokens": 8000 },
"suggesties": [
{ "soort": "LIMIET",
"uitleg": "Je vroeg naar 'de meeste' — sorteer af en neem de top 25.",
"patch": { "limiet": 25, "sorteer": [{…}] } },
{ "soort": "FILTER",
"uitleg": "Beperk tot lopend jaar (412 records).",
"patch": { "waar": { "ontvangenOp": {"jaar": 2026} } } },
{ "soort": "AGGREGEER",
"uitleg": "Of groepeer per status (7 rijen).",
"patch": { "groepeer": ["status"] } }
]
}
{
"toegelaten": false,
"code": "RECHT_ONTBREEKT",
"geweigerd": [
{ "element": "Polis.premieJaarlijks",
"klasse": "FINANCIEEL",
"ontbreekt": "lees:FINANCIEEL",
"rolAanvrager": "SCHADEBEHANDELAAR" }
],
"welToegestaan": ["Polis.nummer", "Polis.status",
"Polis.dekkingstype", "Polis.ingangsdatum"],
"boodschap": "Premiebedragen vallen onder FINANCIEEL. Aantallen, " +
"statussen en dekkingen zijn wel beschikbaar."
}
De aanvrager kan nu twee dingen: opnieuw vragen zonder het bedrag — aantallen zijn vaak al een bruikbaar antwoord — of de gebruiker uitleggen welk recht ontbreekt. Beide zijn beter dan een lege tabel of een cryptische fout.
De redeneerlaag is de vervangbare laag: hier leven de modellen en de agenten, en hier leeft bewust géén enkele veiligheidseigenschap. De laag kent geen opslag, geen rechten en geen afbakening — alles wat ze wil, vraagt ze door de gateway. Daardoor is een modelwissel een configuratiewijziging (principe 10) en groeit de waarde mee met elke generatie betere modellen, zonder dat het risico meegroeit (§1.3).
De vijf blokken uit de band worden elk in een eigen sectie uitgewerkt: orkestratie (§2.5.A — wie doet wat), provider-adapters (§2.5.B — hoe modellen inwisselbaar blijven), de agentlus (§2.5.C — hoe één agent werkt, ronde voor ronde), het antwoordcontract (§2.5.D — de vaste vorm van elk antwoord) en de autonomieladder (§2.5.E — de bestuurde as waarlangs deze laag meegroeit met de modellen; het antwoord op "werkt dit nog over drie jaar?").
Eén vraag wordt zelden door één agent beantwoord. De orkestratie verdeelt het werk over vier vaste rollen — en die rollen zijn declaraties in de configuratie, geen klassen in code: een rol toevoegen of bijstellen is configuratie plus een prompt.
| Rol | Opdracht | Mag deze aanroepen | Denkt met | Grenzen |
|---|---|---|---|---|
| Router | Classificeert de vraag (complexiteit), splitst in deelvragen, kiest de domeinen uit het kennisregister | kennis.register | LICHT | 1 ronde |
| Analist | Beantwoordt één deelvraag: kennis ophalen, catalogus lezen, bevragingen samenstellen, resultaat duiden | alle zes leescalls | WERKER | 8 rondes, 6 bevragingen |
| Synthese | Voegt de bevindingen van de analisten samen tot één antwoord in het antwoordcontract (§2.5.D) | — (ziet alleen bevindingen) | WERKER / FRONTIER | 1 ronde |
| Criticus | Hercontroleert het hoofdcijfer met een onafhankelijk samengestelde bevraging; meldt afwijkingen | bevraag.plan · voer_uit | CRITICUS | 2 rondes |
De router bepaalt de vorm van de graaf: bij een enkelvoudige vraag handelt één analist alles af, zonder synthese; bij een samengestelde vraag (één domein, meerdere metingen) komt de synthese erbij; bij een domeinoverstijgende vraag draaien meerdere analisten parallel — elk met uitsluitend de kennisdocumenten en het toolsubset van hun eigen domein — en weegt de synthese hun bevindingen. De criticus draait alleen wanneer het antwoord een cijfer draagt dat een beslissing kan sturen.
Geen enkele agent praat rechtstreeks met een leverancier. Alles loopt door één neutraal contract; per leverancier vertaalt een adapter dat contract naar diens eigen formaat — en nergens anders leeft leverancierspecifieke vorm.
// De enige interface die orkestratie en agenten kennen.
interface ModelProvider {
naam: string
eigenschappen: {
gestructureerdeAanroep: boolean // native function calling?
streaming: boolean
contextcache: boolean
contextvenster: number
// Bepalend voor MODEL_BEPERKING uit de policy:
verwerkingslocatie: "EU" | "VS" | "ON_PREM" | "ANDERE"
trainingOpInvoer: boolean
retentieDagen: number
certificeringen: string[] // ISO 27001, SOC 2, …
}
genereer(v: Verzoek): Promise<Antwoord>
}
Eén per leverancier, plus één OpenAI-compatibele adapter die de meeste zelf-gehoste en lokale servers in één keer dekt. Vertaling van het neutrale aanroepschema naar het formaat van de leverancier gebeurt binnen de adapter en nergens anders.
Ondersteunt een model geen gestructureerde aanroepen, dan valt de adapter terug op een JSON-modus met schemavalidatie en herkansing. De orkestratie merkt geen verschil; de eigenschappen-vlaggen sturen dat.
Providerstoring is een routeringsgebeurtenis, niet een storing van de dienst. Concentratierisico bij één leverancier is voor gereguleerde instellingen een expliciete toezichtzorg — hier is het een configuratieregel.
Agentcode noemt nooit een model. Ze vraagt om een rol; de routeringstabel in de bestuurslaag (§2.3.D) bepaalt wat die rol vandaag betekent — per organisatie-eenheid, zonder deploy wijzigbaar.
| Rol | Waarvoor | Doorslaggevende eigenschap | Aandeel verkeer |
|---|---|---|---|
| Licht | Classificeren, routeren, herformuleren | Latency en prijs | ± 40% |
| Werker | Bevragingen samenstellen, resultaten duiden, deelantwoorden | Betrouwbaarheid van gestructureerde aanroepen — hier het belangrijkst | ± 45% |
| Frontier | Synthese over domeinen, tegenstrijdigheden wegen, oordeelsvorming | Redeneerdiepte; kosten wegen minder want zeldzaam | ± 10% |
| Criticus | Onafhankelijke controle van het hoofdcijfer | Bij voorkeur een andere leverancier — diversiteit is hier de waarde | ± 5% |
De criticus is de vertaling van challenger model uit klassiek modelrisicobeheer: bij voorkeur een andere leverancier dan de werker, want diversiteit is hier de waarde. Verschil tussen werker en criticus is geen fout maar een signaal — en het wordt gelogd, niet weggepoetst.
Elke rol uit §2.5.A draait op dezelfde motor: een lus die het model laat denken, zijn gateway-aanroepen uitvoert, de resultaten teruggeeft en opnieuw laat denken — tot er een antwoord is of een grens bereikt wordt.
De synthese schrijft geen vrije tekst die daarna geparsed moet worden: ze wordt via een gedwongen structuur (tool-keuze) verplicht deze envelop in te vullen. Eén envelop, meerdere weergaven — en daardoor kán het cijfer in de export niet afwijken van het cijfer op het scherm.
type Antwoordenvelop = {
antwoord: string // markdown, kort, in de taal van de gebruiker
kernwaarde?: { label: string; waarde: number|string; eenheid?: string
toon?: "neutraal"|"positief"|"waarschuwing"|"kritiek" }
tabel?: { kolommen: Kolom[]; rijen: Rij[] } // getypeerd: geld/datum/tekst/getal
grafiek?: { soort: "staaf"|"lijn"|"donut"; … }
aannames: string[] // VERPLICHT — "Periode: 2026 (aangenomen)",
// kwaliteitsnotities uit het register
bronnen: Bron[] // per cijfer: bevragingshash, spec, rijaantal,
// afgekapt-vlag — het audit-spoor (§2.6)
vervolgvragen: string[] // max 3, klikbaar
}
Drie regels maken dit contract meer dan een formaat. Eén: de renderers zijn deterministisch — tekst, KPI-tegel, tabel, PDF en spreadsheet worden alle uit dezelfde envelop opgebouwd, en het model schrijft nooit zelf het bestand (een model dat een rapport hertikt, hertikt vroeg of laat een cijfer fout). Twee: aannames is verplicht en mag niet leeg zijn wanneer er iets aangenomen wérd — een stilzwijgende aanname in een stellig geformuleerd antwoord is precies wat een chat gevaarlijker maakt dan een dashboard. Drie: bronnen draagt de volledige herkomst, zodat "hoe kom ik hieraan?" één klik is en elk cijfer natelbaar blijft tot op de bronrij (principe 8).
Hoe een systeem meegroeit met capaciteit zonder herbouw. Dezelfde gateway, dezelfde policy-engine; wat verandert is welke handelingen verleend zijn — per rol, per domein, per omgeving.
Zonder deze laag is het systeem een orakel. Met deze laag is het een bedrijfsmiddel dat zich kan verantwoorden tegenover een auditor, een toezichthouder en een betrokkene die inzage vraagt.
Per gesprek een boom: elke ronde met modelrol, provider, prompt-hash, tokens, kosten, duur — en per gateway-aanroep de specificatie, de policy-beslissingen, de raming, het rijaantal en de bevragingshash. Bewaartermijn en redactie zijn zelf beleid: traces bevatten data, dus vallen ze onder hetzelfde regime.
Een trace opnieuw uitvoeren tegen een ander model of een nieuwere registerversie en de verschillen tonen. Dit maakt van een modelwissel een meting in plaats van een gok: draai de laatste duizend gesprekken opnieuw, vergelijk uitkomsten en kosten, beslis daarna. Het is ook het regressiemechanisme voor wijzigingen in de semantische laag.
Gouden vragen in de bouwstraat, in drie soorten: correctheid (klopt het cijfer tegen een onafhankelijk berekende waarheid), veiligheid (een aanvraag namens A raakt geen record van B; een beperkte rol krijgt geen beschermde klasse), zuinigheid (blijft het aantal rondes en de kost binnen de grens).
Voor een gereguleerde instelling is dit de sectie die bepaalt of het systeem in productie mag. De afbeelding is bewust op componenten, niet op beloften.
| Kader | Kernverplichting | Waar de architectuur dat draagt |
|---|---|---|
| EU AI-verordening | Risicoclassificatie; registratie van gebeurtenissen gedurende de levensduur; menselijk toezicht; transparantie naar gebruikers | De trace ís het gebeurtenissenlogboek — met invoer, beslissingen en uitkomst per stap. De autonomieladder maakt menselijk toezicht een verleningsbeslissing per handeling in plaats van een intentie. Classificatie van het gebruik volgt uit het handelingsregister: adviseren is een ander risicoprofiel dan beslissen. |
| AVG / GDPR | Doelbinding, minimale gegevensverwerking, rechtmatige grondslag, rechten van betrokkenen, geen louter geautomatiseerde besluiten met rechtsgevolg | Grondslag per veld in het register; doelbinding als verplichte parameter en toetsingsstap; minimalisatie afgedwongen door projectie en drempels; de trace beantwoordt een inzageverzoek; art. 22 wordt gedragen doordat besluitvormende handelingen op L4 of lager staan. |
| DORA | Beheersing van ICT-risico bij derden; concentratierisico; uitwijk en exitstrategie | Providerabstractie maakt van uitwijk een routeringsregel. Meerdere providers naast elkaar verlagen concentratierisico structureel; de exitstrategie is aantoonbaar omdat herspelen laat zien dat de dienst op een andere leverancier dezelfde uitkomsten geeft. |
| BCBS 239-beginselen | Nauwkeurigheid, volledigheid en herleidbaarheid van risicodata-aggregatie | Gecertificeerde metrieken met eigenaar en herzieningsdatum; herkomst tot op de bronrij; registerversie vastgelegd bij elk resultaat, zodat een cijfer van vorig kwartaal reproduceerbaar blijft. |
| Solvency II / EIOPA | Datakwaliteit voor rapportage; beheersing van modelrisico; verantwoordingsplicht bestuur | Kwaliteitsnotities per resource die automatisch in de aannames van een antwoord belanden; criticus-agent als challenger; evaluatieverzameling als doorlopende validatie; bestuur ziet één catalogus met eigenaars. |
| Datasoevereiniteit | Beperkingen op verwerkingslocatie per gegevenscategorie | MODEL_BEPERKING koppelt gegevensklasse aan providereigenschappen. Persoonsgegevens routeren automatisch naar EU-verwerking; bijzondere categorieën naar eigen infrastructuur — afgedwongen, niet afgesproken. |
Wie vraagt wat, wat kost het, en wat levert het op. Zonder deze cijfers wordt elk AI-programma na een jaar een discussie op basis van meningen.
De sturing zelf is beleid, geen code: budgetplafonds per gesprek, per gebruiker per dag en per eenheid per maand, met een instelbaar gedrag bij overschrijding — weigeren, degraderen naar een goedkoper model, of doorlaten met melding. Alle drie zijn verdedigbaar in verschillende contexten; de keuze hoort bij de eigenaar van het budget, niet bij de ontwikkelaar.
De toets op generaliseerbaarheid. Links een middelgrote multi-tenant ERP-omgeving, rechts een internationale verzekeraar. Dezelfde vijf lagen, dezelfde negen stappen, dezelfde ladder — andere invulling.
| Architectuurbegrip | ERP — reference implementation | Internationale verzekeraar |
|---|---|---|
| Afbakeningsas 1 | Tenant (werkmaatschappij binnen een groep) | Entiteit per land / branche, met verschillende toezichthouders |
| Afbakeningsas 2 | Juridische entiteit voor financiële gegevens | Rechtsgebied plus distributiekanaal (eigen net, makelaar, volmacht) |
| Kernresources | Opportuniteit, project, factuur, werkopdracht, planning | Polis, dekking, schadeclaim, premie, reserve, herverzekeringscessie, tussenpersoon |
| Gecertificeerde metrieken | Omzet, onderaannemerskost, marge, openstaand saldo | Schaderatio, gecombineerde ratio, IBNR-reserve, technisch resultaat, klantwaarde |
| Bijzondere klasse | Contactgegevens, personeelsdocumenten | Medische dossiers bij letselschade, strafrechtelijke gegevens bij fraudeonderzoek |
| Tier-3 precedent | Eerdere calculatiebesluiten, afwijkende afspraken per klant | Eerdere schaderegelingen in grensgevallen, acceptatiebeslissingen, interpretaties van polisvoorwaarden |
| Typische L2-vraag | "Welk project had de laagste marge en lag dat aan kosten of prijs?" | "Welke tussenpersonen verslechterden in schaderatio motor 2024, en zit dat in frequentie of in gemiddelde last?" |
| Typische L4-handeling | Een herinnering versturen; een planning verschuiven | Een reserve bijstellen binnen mandaat; een routinematige claim afhandelen onder drempel |
| Zwaarste eis | Geen kruisverkeer tussen tenants; natelbaarheid van elk financieel cijfer | Datasoevereiniteit per rechtsgebied; herleidbaarheid voor toezicht; geen louter geautomatiseerde besluiten richting verzekerden |
| Schaalverschil | Tientallen gebruikers, miljoenen rijen | Duizenden gebruikers, miljarden rijen, tientallen bronsystemen |
Architectuur zonder eigenaarschap verwatert binnen twee kwartalen. Dit is de verdeling die maakt dat de lagen onderhouden blijven.
| Artefact | Eigenaar | Goedkeuring | Ritme |
|---|---|---|---|
| Semantisch register — velden, relaties | Domein-data-eigenaar | Code-review + bouwstraatcontrole | Bij elke schemawijziging |
| Gevoeligheidsklassen en grondslagen | Privacy- en informatiebeveiliging | Vieroog, vastgelegd | Bij nieuwe velden; jaarlijkse herziening |
| Gecertificeerde metrieken | Functionele eigenaar (Finance, Actuariaat, Commercie) | Eigenaar + risicobeheer | Bij definitiewijziging; herzieningsdatum verplicht |
| Policy — rol × klasse × actie | Informatiebeveiliging | Vieroog + simulatie vóór inwerkingtreding | Bij organisatiewijziging |
| Kennistiers 1–3 | Domeinexperts | Vakinhoudelijke review | Doorlopend; tier 3 groeit per afgehandeld grensgeval |
| Modelroutering en budgetten | AI-platformteam | Eigenaar + inkoop bij nieuwe leverancier | Per kwartaal of bij marktverandering |
| Evaluatieverzameling | AI-platform samen met domeinexperts | Bouwstraat blokkeert bij regressie | Groeit met elke fout die gevonden wordt |
| Autonomieverleningen (L3+) | Business-eigenaar van het proces | Risicobeheer; onderbouwd met trace-bewijs | Per proces, met evaluatie na inwerkingtreding |
Deze architectuur is geen eigen uitvinding die de lezer op gezag moet aannemen. Ze is de vendor-neutrale beschrijving van het patroon waar de grote platformen en de semantische-laag-markt in 2025–2026 onafhankelijk van elkaar op geconvergeerd zijn. Dat is een sterkte: het patroon is gevalideerd; wat dit document toevoegt is de samenhang en het beslissingskader.
| Laag (dit document) | Microsoft | AWS / Google | Databricks / Snowflake | Onafhankelijke spelers |
|---|---|---|---|---|
| Kennislaag | Foundry-kennisbronnen, Copilot-grounding | Bedrock Knowledge Bases / Vertex AI Search | — | Retrieval-platformen; de tier-structuur met precedent is zeldzaam en meestal klantwerk |
| Bestuurslaag | Purview (classificatie, labels), Entra Agent ID | Bedrock Guardrails-policies / Vertex-governance | Unity Catalog / Horizon | Immuta, Collibra; OPA en Cedar voor policy-as-data |
| Gateway | AI Agent Landing Zone, Foundry Agent Service | Bedrock Agents + Guardrails / Agent Builder | Unity AI Gateway / Cortex Analyst semantic models | Cube, AtScale (semantische laag met compile-time-rechten); Kong, Portkey, LiteLLM (modelverkeer) |
| Redeneerlaag | Foundry-modelcatalogus, multi-model routing | Bedrock-modelkeuze / Vertex Model Garden | Model serving endpoints | Portkey, LiteLLM, OpenRouter — routing, failover, kostenmeting |
| Bewijslaag | Purview-audit, Foundry-tracing | CloudWatch/Bedrock-invocatielogs / Vertex-tracing | Lakehouse Monitoring | Langfuse, Arize, Braintrust — traces, evals, kostentoerekening |
Twee observaties die het beslissingskader vormen:
De gevestigde data-gateways en semantische lagen zijn gebouwd voor analytische platformen — warehouse en lakehouse. Voor een organisatie waarvan de data daar al ligt, is kopen de voor de hand liggende route en wordt dit document het evaluatiekader. Voor een operationeel systeem op een transactionele database — zoals de reference implementation — bestaat er geen passend product van de plank, en is een dunne eigen gateway op het bestaande autorisatiemodel de kortere en veiligere weg. Grote organisaties doen doorgaans beide: kopen voor het analytische landschap, bouwen voor de operationele kernen.
Geen enkel platform kan de data van de klant classificeren, de metrieken definiëren of de domeinkennis vastleggen. Een classificatietool herkent een telefoonnummer, maar niet dat een gefactureerde vordering niet als omzet telt. Het semantisch register, de gecertificeerde metrieken en de kennistiers zijn bij elke opzet klantwerk — dat is dus geen overhead die deze architectuur toevoegt, maar de kern die hoe dan ook gedaan moet worden. De architectuurkeuze bepaalt alleen of dat werk één keer gebeurt, op één plek, met één eigenaar — of verspreid en impliciet in elke integratie opnieuw.
Een expliciete toets: als de redeneerder over drie jaar aanzienlijk capabeler is dan een menselijke expert, welke onderdelen van dit ontwerp houden stand en welke moeten mee-evolueren?
| Onderdeel | Uitkomst | Waarom |
|---|---|---|
| Afbakeningsinjectie | Ongewijzigd | Klasse 3. Werkt identiek ongeacht wie vraagt — dat is de definitie van capaciteitsonafhankelijk. |
| Policy-evaluatie | Ongewijzigd | Idem. Wordt niet zwakker doordat de aanvrager slimmer is. |
| Toelatingscontrole | Drempels stijgen | Het mechanisme blijft; een capabeler model verdient een ruimer venster omdat het beter met meer data omgaat. Een instelling, geen herbouw. |
| Bevragingstaal | Verrijkt | Sterkere modellen stellen complexere bevragingen samen. Vensterfuncties, cohortanalyse, tijdreeksen komen erbij — als uitbreiding van de taal, niet als omweg eromheen. |
| Aantal agentrollen | Neemt af | Router, analist en synthese bestaan omdat huidige modellen baat hebben bij contextscheiding. Een capabeler model doet dat zelf. De graafconfiguratie krimpt; de gateway eronder verandert niet. |
| Kennistiers | Waardevoller | Een sterkere redeneerder haalt méér uit precedent, niet minder — hij herkent scherper welk eerder geval van toepassing is. Tier 3 wordt belangrijker naarmate de redeneerder beter wordt. |
| Autonomieniveau | Stijgt bewust | Van L2 naar L4 en voor sommige processen L5. Een verleningsbeslissing per rol en domein, onderbouwd met trace-bewijs uit het niveau eronder. |
| Verificatie door mensen | Verschuift wezenlijk | Redenering nalezen verliest zijn waarde. Bewijsketens en steekproeven op uitkomsten nemen het over. Dit is de enige verandering die architectuur vooraf moet dragen — achteraf inbouwen kan niet. |
| Prompt als sturing | Verliest werking | Klasse 1 degradeert. Wie er veiligheid op bouwde, moet dan herbouwen. Wie hem alleen voor kwaliteit gebruikte, merkt er niets van. |
Wat deze architectuur expliciet afwijst, en waarom. Het eerste punt is een correctie op mijn eigen eerste ontwerp — de fout is leerzaam genoeg om te tonen.
| Patroon | Waarom het aantrekkelijk lijkt | Waarom het faalt |
|---|---|---|
| Toolwildgroei — één tool per vraagsoort | Elke tool is afzonderlijk veilig en makkelijk te begrijpen | Het vraagbereik is begrensd door de verbeelding van de ontwerper; de catalogus groeit tot ze zelf niet meer in de context past; elke nieuwe vraag vraagt een release. Dit was de fout in de eerste versie van dit ontwerp. |
| Prompt als beleid | Snel, flexibel, geen infrastructuur nodig | Klasse 1: niet afdwingbaar, niet bewijsbaar, niet uitputtend testbaar — en degradeert precies wanneer de modellen beter worden. |
| Directe SQL-generatie op productie | Maximale flexibiliteit, snel te demonstreren | Afbakening niet afdwingbaar, definities worden herleid in plaats van gebruikt, onbegrensde resultaten, injectie-oppervlak, en niets is reproduceerbaar. |
| Vector-retrieval als standaardantwoord | Eén patroon voor alles; volwassen gereedschap | Uitstekend voor ongestructureerde tekst, ongeschikt voor precieze aggregatie over gestructureerde data. Benaderend zoeken levert benaderende cijfers — onaanvaardbaar voor financiële en actuariële vragen. Beide naast elkaar, elk voor waar het thuishoort. |
| Alles in de context stoppen | Grote contextvensters lijken het probleem op te lossen | Kosten schalen lineair met ruis, precisie daalt bij irrelevante inhoud, en de rechtenvraag verdwijnt niet — hij wordt alleen onzichtbaar. |
| Menselijk toezicht als vinkje | Voldoet ogenschijnlijk aan de eis | Een goedkeurder die tien voorstellen per minuut ziet, keurt goed. Toezicht werkt alleen met begrensd volume, echte weigermogelijkheid en zichtbaar bewijs — anders is het schijnzekerheid met een auditspoor. |
| Leverancierspecifieke koppeling | Het snelste pad naar een werkende demo | Formaten, aanroepconventies en eigenaardigheden lekken in de bedrijfslogica. Wisselen wordt een project in plaats van een instelling — en toezichthouders vragen inmiddels naar uitwijk. |
Wat na dit alles nog moeilijk blijft. Een referentiearchitectuur die alleen de opgeloste problemen benoemt, is een verkoopdocument.
Met een open bevragingstaal kan een redeneerder twee sommen combineren en het resultaat een naam geven die met de gezaghebbende definitie botst. Vier verdedigingslagen — gecertificeerde metrieken, niet-aggregeerbare basisvelden, zelflabeling van antwoorden als gezaghebbend of zelf samengesteld, en een criticus met een onafhankelijke bevraging — verkleinen het maar sluiten het niet uit. Daarom is natelbaarheid geen extra, maar de voorwaarde waaronder financiële antwoorden gepresenteerd mogen worden.
De bouwstraatcontrole voorkomt achterlopen, maar verlegt de last naar elk schemavoorstel. In een grote organisatie met tientallen domeinteams is dat federatief bestuur met alle bijbehorende afstemming. Het is bewust — het is de prijs van principe 3 — maar het moet begroot worden, niet weggewuifd.
Eén gezaghebbende metriek betekent dat iemands bestaande rapportage ongelijk krijgt. Dat is een bestuurlijk vraagstuk met eigenaars en belangen, en het is doorgaans het traagste onderdeel van het traject. Techniek kan het zichtbaar maken; beslissen moet de organisatie zelf.
Een perfect herleidbaar antwoord op een verkeerd gestelde vraag blijft misleidend, en een correct cijfer over een periode die niet representatief is, is nog steeds een verkeerd inzicht. Vandaar de verplichte aannames in elk antwoord en de kwaliteitsnotities per resource — maar de laatste beoordeling of de vraag de juiste was, blijft menselijk. Dat is geen tekortkoming van dit ontwerp; het is de grens van wat een systeem over zichzelf kan weten.
Vensterfuncties over onregelmatige tijdvensters, recursieve hiërarchieën, statistische procedures. Twee eerlijke uitwegen: de taal uitbreiden wanneer een patroon zich herhaalt, of een streng afgeschermde escape met eigen recht, menselijke bevestiging en verplichte herkomst. Doen alsof die vijf procent niet bestaat, leidt tot schaduwoplossingen buiten de gateway — en dat is erger dan een bestuurde uitzondering.
De volgorde is bewust: bestuur vóór intelligentie. De eerste twee fasen leveren geen zichtbare chat op — en zonder die twee bouw je een systeem waarvan je de veiligheid achteraf moet bewijzen, wat niet lukt.
| Fase | Wat | Inhoud | Klaar wanneer |
|---|---|---|---|
| 0 | Semantiek en policy | Register met classificatie en afbakeningspaden voor vijf kernresources; policy-engine met verplichtingen; bouwstraatcontrole op ongeclassificeerde velden | Veiligheidstests groen: geen kruisverkeer tussen afbakeningen; beperkte rol krijgt geen beschermde klasse |
| 1 | Gateway | Bevragingstaal, compiler met gecorreleerde subbevragingen, afbakening over relatiepaden, raming, toelating, lees-only rol, zes aanroepen. Nog geen AI. | Een niet-voorziene analytische vraag draait via de API vanuit een testscript |
| 2 | Redeneerlaag | Providerinterface met één adapter, agentlus, router/analist/synthese, modelrollen uit configuratie, volledige trace | Vragen die niemand vooraf bedacht heeft worden end-to-end beantwoord, met herkomst |
| 3 | Interface en oplevering | Gespreksinterface met zichtbare stappen, herkomst uitklapbaar, doorklik naar bronrijen, export | Bruikbaar zonder tussenkomst van een ontwikkelaar |
| 4 | Bestuur zichtbaar | Beheerschermen voor rechten, catalogus en gesprekken; tweede provider-adapter; herspelen; evaluatieverzameling; criticus | Modelwissel is een instelling met een meting; rechten zijn simuleerbaar vóór inwerkingtreding |
| 5 | Verbreding en autonomie | Register uitbreiden per domein; tier-3-precedent opbouwen; handelingsregister; L3 en daarna L4 voor geselecteerde processen | Autonomie wordt verleend op basis van bewijs uit de trace van het niveau eronder |
"Welke opportuniteiten hebben de meeste interacties en de meeste e-mailcommunicatie?" — een vraag waarvoor niets is voorbereid. Dit is de toets die de hele architectuur moet doorstaan.
Classificeert met het domeinregister in de gecachte systeemprompt: samengestelde vraag, één domein met een raakvlak. Eén analist, synthese, geen criticus — er is geen financieel cijfer in het spel.
Haalt tier 1 van het commerciële domein op. Leert de statusverlopen, en dat interacties polymorf zijn opgeslagen met een typeveld — waardoor hij straks niet per ongeluk interacties van andere entiteitsoorten meetelt. Dat is precies het soort domeinkennis dat het verschil maakt tussen een cijfer dat klopt en een cijfer dat plausibel oogt.
Vraagt het register voor Opportuniteit en ziet velden, klassen, toegangsannotaties en relaties. Merkt dat de relatie naar conversaties verwijst naar een resource die zélf berichten heeft, vraagt in dezelfde ronde ook die op, en kent daarmee het tweestapspad.
Stelt zijn eerste specificatie samen en laat hem droogdraaien. De gateway autoriseert alles, injecteert de afbakening, raamt 2.014 rijen ≈ 41k tokens en weigert met drie verfijnsuggesties. Geen data — wel richting.
Neemt de suggestie over en verfijnt zelf verder: alleen inkomende berichten, want communicatie van de klant is een betere maat voor betrokkenheid dan eigen verzonden post. Die afweging is precies het stuk dat je niet in een tool kan vastleggen — en de reden dat het vraagbereik open moet zijn.
{ "van": "Opportuniteit",
"selecteer": ["id", "naam", "status", "klant.naam"],
"meet": [
{ "als":"interacties", "tel":"interacties" },
{ "als":"inkomendeMail","tel":"conversaties.berichten",
"waar":{ "richting":"IN" } },
{ "als":"laatsteContact","max":"interacties.datum" } ],
"sorteer": [{"veld":"interacties","richting":"af"},
{"veld":"inkomendeMail","richting":"af"}],
"limiet": 25 }
De compiler maakt géén koppelingen maar gecorreleerde subbevragingen — anders bederft val 1 uit §2.4.B beide tellingen — en injecteert de afbakening die de agent niet gevraagd heeft en niet kan weglaten:
SELECT o.id, o.naam, o.status, k.naam AS klant_naam,
(SELECT count(*) FROM interacties i
WHERE i.opp_id = o.id AND i.entiteit_type = 'opportuniteit') AS interacties,
(SELECT count(*) FROM berichten b
JOIN conversaties c ON c.id = b.conversatie_id
WHERE c.opp_id = o.id AND b.richting = 'IN') AS inkomende_mail,
(SELECT max(i.datum) FROM interacties i WHERE i.opp_id = o.id) AS laatste_contact
FROM opportuniteiten o
LEFT JOIN organisaties k ON k.id = o.klant_id
-- afbakeningsinjectie: niet gevraagd, niet weg te laten
WHERE EXISTS (SELECT 1 FROM opp_tenants t
WHERE t.opp_id = o.id AND t.tenant_id = ANY($1))
ORDER BY interacties DESC, inkomende_mail DESC
LIMIT 25;
Duiding, de tabel van 25, de aannames ("betrokkenheid gemeten als inkomende berichten plus geregistreerde interacties; alle jaren"), de herkomst (één bevraging, hash, 25 van 2.014 na sortering) en twee vervolgvragen.
"Welke tussenpersonen verslechterden het sterkst in schaderatio op motorrijtuigen 2024, en zit die verslechtering in frequentie of in gemiddelde schadelast?"
Dezelfde vijf lagen, drie verschillen die de sectorspecifieke eisen dragen:
| Aspect | Uitwerking |
|---|---|
| Gezaghebbende metriek | Schaderatio wordt niet door de redeneerder samengesteld. Het is een gecertificeerde metriek met een eigenaar bij Actuariaat, met de vastgelegde behandeling van IBNR, schaderegelingskosten en herverzekeringsherstel. De basisvelden staan op niet-aggregeerbaar, dus een zelfbedachte variant wordt geweigerd met verwijzing naar de metriek. De ontleding naar frequentie en gemiddelde last zijn twee aanvullende gecertificeerde metrieken — precies de decompositie die de vraag stelt. |
| Afbakening | Twee assen tegelijk: de entiteit die het risico draagt (rechtsgebied en toezichthouder) en het distributiekanaal. Een gebruiker bij de Belgische entiteit ziet geen Franse portefeuille, ook niet in een totaal — en het aggregaat verraadt dat verschil niet, want de injectie zit in de subbevraging. |
| Modelbeperking | Het antwoord bevat geen persoonsgegevens — het gaat over tussenpersonen en portefeuilles — dus de volledige providerverzameling is toegestaan. Zou dezelfde analyse afdalen naar individuele schadedossiers met letselgegevens, dan vernauwt de policy de toegestane modellen automatisch tot on-premise verwerking, zonder dat iemand daaraan hoeft te denken. |
| Tier 3 | Bij de duiding van uitschieters raadpleegt de analist eerdere acceptatiebeslissingen en portefeuillesaneringen: is deze verslechtering al eens vastgesteld en welke maatregel volgde? Dat maakt het verschil tussen een correct cijfer en een bruikbaar advies. |
| Autonomie | Blijft op L2 — analyseren en rapporteren. Een portefeuillemaatregel voorstellen is L3 en vraagt een expliciete verlening; een commissie of mandaat effectief aanpassen is L4 met vieroogprincipe. De architectuur draagt alle drie; de organisatie beslist waar de grens vandaag ligt. |