Wie vult het formulier in? — We tekenen alleen wat het model heeft opgesteld
Het probleem ligt echter stroomopwaarts. Het model bepaalt namelijk wát er gevraagd wordt. Het vraagt naar alles wat ontbreekt. Als het model er niet bij kan herkennen dat het iets niet weet, vraagt het niet. En als het een leeg veld zelf invult, blijft er niets over om over te vragen. Hoe sterk de instructie ook is geformuleerd, het loopt telkens vast op hetzelfde punt.
De handtekening bleef, het concept verschoof
Een formulier bestond voorheen uit vijf stappen. De gebruiker bepaalde wanneer en onder welke omstandigheden er gehandeld moest worden, selecteerde het formulier, voerde de waarden in, controleerde waar die waarden vandaan kwamen en bevestigde dat elk verplicht veld was ingevuld. Het invoeren van de waarden was dus een menselijke taak: een persoon keek naar elk leeg veld, vulde dit in en drukte vervolgens op bevestigen.
Een mens bevestigt nog steeds aan het einde. De goedkeuring is niet verdwenen. Wat is echter verschoven, is het eerste concept. Het model vult nu de waarden in het formulier in. De persoon kijkt nu naar het gepresenteerde formulier en tekent dit.
Hierdoor verandert de aard van de controle. Het is niet langer "is dit correct?", maar "gaan we hiermee akkoord?". De eerste vraag vereist een oordeel; de tweede is simpelweg een doorgeefluik. Als je iemand vraagt om goedkeuring te geven voor wat je hem hebt getoond, krijg je vaak een snelle klik in plaats van een echte review.
Erger nog is dat het formulier er "schoon" uitziet. Als het er slordig uit zou zien, zou je dat direct merken. Maar een opgezochte waarde en een verzonnen waarde zien er identiek uit. Het lezen van het formulier vertelt je dus niets, en een ontbrekende voorwaarde verschijnt helemaal niet op het formulier. Er is niets dat onthult dat je een veld goedkeurt dat je in werkelijkheid nooit hebt gecontroleerd.
Wat dus teruggehaald moet worden, is niet de handtekening, maar het opstellen van het concept.
De verschuiving
Behandel wat er voorafgaat aan de uitvoering niet als validatie, maar als een proces dat vragen stelt op basis van een externe lijst. Gezien als validator gaat het werk over het verfijnen van de criteria voor een oordeel. Gezien als een plek waar vragen worden gesteld, gaat het werk over wát er gevraagd wordt.
In plaats van het probleem op te lossen door het model nauwkeuriger te maken, is de oplossing: een externe lijst bepaalt wat er gevraagd moet worden, en het model stelt de vragen.
Dat is het kernargument van dit stuk. De huidige aanpak stelt al vragen. Wat essentieel is, is wie bepaalt welke vragen er gesteld worden.
Je kunt vragen naar de betrouwbaarheid van wat er aanwezig is, maar je kunt niet vragen naar het bewustzijn van wat er ontbreekt. Dat is de reden waarom zelfs een ervaren chirurg een checklist gebruikt.
Wat in het formulier komt, is niet iets om af te leiden (inferentie), maar iets om op te zoeken. En daarvoor is de gebruiker de enige bron. Betere computatie zorgt er niet voor dat ontbrekende informatie plotseling bestaat.
Fouten komen zo aan het oppervlak. Een verkeerde berekening laat geen zichtbaar spoor na, maar wanneer je het vraagt, zegt de gebruiker "nee". Er ontstaat een correctiepad.
En hier is de rol van de lijst bepaald: als niet extern is gedefinieerd wat er gevraagd moet worden, gaat dat oordeel weer terug naar het model.
Het doel veranderen
Twee termen worden vooraf gedefinieerd:
- Slot: één regelpost die bevestigd moet worden voor deze uitvoering.
- Unknown (Onbekend): een slot dat leeg blijft nadat elke aangewezen bron is gecontroleerd.
Maak het doel van de computatie de lijst van unknowns, niet de beslissing of er uitgevoerd moet worden. Of er wordt uitgevoerd, volgt uit de lengte van die lijst; het is niet het doel op zich. Het corrigeren van een fout antwoord wordt zo ook een kwestie van het vullen van één slot.
Als het doel uitvoering is, ontstaat er een volgorde tussen de slots. Als het doel de lijst is, hebben de slots geen betrekking meer op elkaar. Het toevoegen van een stap klinkt alsof het langzamer zou zijn, maar het tegendeel is waar: opzoekacties (lookups) draaien parallel, het zijn geheugenvergelijkingen in plaats van extra inferentie-aanroepen, en de herhaalde interacties om één voor één naar lege velden te vragen, worden samengevoegd tot één interactie.
Als het doel de lijst is, wordt het oordeel gescheiden van de uitvoering. Als de uitvoering alleen een geregistreerd oordeel als basis accepteert, is er geen pad dat zonder dat oordeel kan lopen.
Het gevolg is dat er een lijst moet zijn van wat nodig is, en dat deze moet worden onderverdeeld op basis van waar de informatie zich bevindt.
Welke lijst?
Er zijn tegenwoordig drie manieren waarop een uitvoering misgaat:
- Verkeerde uitvoering: de waarde was onjuist (bijv. een verzonnen rekeningnummer of ID).
- Niet-geïnstrueerde uitvoering: er waren geen voorwaarden. Het werd uitgevoerd zonder controle van autoriteit of timing.
- Off-target uitvoering: de intentie werd niet goed begrepen. Dit was niet wat de gebruiker bedoelde.
De lijst moet daarom ook drie zaken bevatten: waarden, voorwaarden en intentie.
Twee hiervan bestaan al: de tool-lijst en het input-schema. Er hoeft niets nieuws gebouwd te worden; de aanvullende informatie komt hierbij.
Waarden alleen zijn niet genoeg
Het input-schema bevat waarden, en niets anders. Maar voorwaarden moeten ook ingevuld zijn voordat er iets kan draaien. Is het saldo voldoende? Bestaat de ontvanger? Wanneer gebeurt dit? Onder welke omstandigheden? Is er autoriteit? Zijn veiligheidsoverwegingen behandeld? Dit is het punt waar elk argument aanwezig is en elk type klopt, maar de actie nog steeds niet mag worden uitgevoerd.
Door waarden en voorwaarden op dezelfde lijst te zetten, is er één manier om beide te behandelen. Beiden zijn slots; elk is ofwel ingevuld of niet. Er is geen aparte machine voor voorwaarden nodig.
Het is niet nodig om iemand te vragen voorwaarden vanaf nul te schrijven. Providers schrijven deze al in de tool-beschrijving. Er is simpelweg geen manier om te bevestigen dat het model deze vrije tekst heeft herkend en daarop heeft gehandeld.
Intentie wordt op dezelfde manier een slot: wat de gebruiker de actie noemt en welke wijziging de gebruiker wil. Als een tool wordt gekozen terwijl deze leeg blijven, is het resultaat een off-target uitvoering.
Een naam is een label; wat een tool kan doen is iets anders. De ene provider kan "zet het licht in de woonkamer uit" noemen turnofflight, een ander setdevicepower, terwijl light_control misschien alleen de helderheid aanpast. De matching moet dus gebaseerd zijn op of de tool de gewenste statuswijziging kan produceren, niet op het matchen van namen.
De organisatie van de lijst
De as voor het verdelen van de slots is: wie kan ze beantwoorden?
Vaste checklist (behoort bij elke uitvoering)
- Welke tool moet worden gekozen.
- Of de uitvoeringsvoorwaarden zijn voldaan (timing en omstandigheid).
- Hoe de gebruiker deze actie noemt.
Provider-checklist (verschilt per tool)
- Verplichte velden, types en formaten.
- Bevestiging voorafgaand aan uitvoering.
- Verbiedende voorwaarden en voorwaarden voor extra goedkeuring.
- Wat er verandert als het wordt uitgevoerd (de statuswijziging die deze tool kan produceren).
Gebruikers-checklist (verschilt per gebruiker en omgeving)
- Intentie, huidige context, uitvoeringslimieten.
- Bevestiging voorafgaand aan uitvoering, voorkeuren.
De vaste zijde betreft intentie en context. De provider- en gebruikerszijde betreffen waarden en voorwaarden.
Waar te zoeken
Een lookup is alleen een lookup als elk slot een aangewezen bron heeft. De zoekvolgorde is als volgt: Antwoord van de gebruiker → de instructie → voingestelde waarden → geobserveerde waarden → vorige status
Dit is een zoekvolgorde, geen ranglijst van vertrouwen. Het betekent niet dat eerdere bronnen betrouwbaarder zijn, maar dat je stopt zodra er een antwoord wordt gevonden.
Als een slot na het controleren van elke bron nog steeds leeg is, is het een unknown. Dit is niet het model dat verklaart dat het het niet weet, maar wat overblijft nadat de zoektocht is beëindigd. Als de waarde nodig is, wordt de gebruiker om antwoord gevraagd.
Nodige waarden worden beantwoord door de gebruiker. Geen inferentie.
Uitsluiten werkt niet, opzoekplekken bieden wel
De instructie "zoek, maar laat weg wat je hebt afgeleid" werkt niet. Wat is weggelaten is van buitenaf niet zichtbaar, en de instructie kan in eerste instantie niet worden uitgevoerd. Omdat een opgehaalde waarde en een verzonnen waarde er hetzelfde uitzien, is vragen om dingen weg te laten hetzelfde als het model vragen zijn eigen output achteraf te classificeren, en die classificatie is opnieuw inferentie.
Het moet dus een whitelist zijn, geen blacklist. Niet: "kijk naar alles en trek de inferenties ervan af", maar: "definieer wat bekeken mag worden, voeg één item per keer toe en leg de bron vast". Dan hoeft er niets geclassificeerd te worden.
Hetzelfde geldt voor de slot-lijst. Niet "laat niets weg wat je moet bevestigen", maar schrijf alles op wat bevestigd moet worden. Een instructie om niets weg te laten werkt alleen voor iemand die weet wat hij heeft weggelaten, en dat is precies wat het model niet kan.
"Geen resultaat" en "Onbekend" zijn verschillend
Het model registreert wat het vindt bij de bron die het controleert. Als daar niets is, is dat "geen resultaat". Dit zijn twee uitkomsten van dezelfde actie, niet twee verschillende oordelen. "Unknown" is de status die overblijft nadat al die rapporten binnen zijn.
"Unknown" zou geen onderdeel van het vocabulaire van het model moeten zijn. Als je "unknown" als een legitieme invoer maakt, krijgt het model een extra antwoord waaruit het kan kiezen. Het moet kunnen schrijven "geen resultaat", want wanneer er niets te schrijven is, gaat het model verzinnen. Het invullen van een leeg veld is getraind gedrag, geen defect; het verdwijnt niet simpelweg door het te verbieden. Wat verzinnen stopt, is niet een verbod, maar een plek om te kunnen zeggen dat er niets is.
Hoe ver reikt de instructie?
Tool-gebruik wordt zelden bepaald door één enkele instructie. De gebruiker begint met een vaag verzoek, een paar uitwisselingen vernauwen wat ze proberen te doen, en aan het eind wordt de tool bepaald. De reikwijdte van het gesprek is dus niet één enkele uitwisseling, maar de gehele interactie tot het punt waarop het tool-gebruik wordt besloten.
Dat definieert ook de reikwijdte van de instructie. Als de instructie die als bron voor waarden wordt gebruikt beperkt is tot de laatste prompt, is een rekeningnummer dat drie beurten geleden werd genoemd nergens te vinden. De instructie beslaat daarom het gehele gesprek, waardoor het aantal waarden dat niet opnieuw gevraagd hoeft te worden, toeneemt.
Splitsen in principes en code
Een principe kan alleen worden gebruikt waar code een schending kan detecteren. Alles waarvan een schending anders onopgemerkt zou blijven, moet in code worden vastgelegd.
Principes
- Neem slots van de lijst, waarden van de lookup, en wat ontbreekt van de gebruiker. Ga niet zelf assembleren.
- Herken wanneer er om iets is gevraagd en hoe het werd genoemd, en bepaal dan de tool.
- Als de timing onduidelijk is, ga dan niet uit van onmiddellijke uitvoering. Vraag het na.
- Als er meer dan één kandidaat overblijft, toon dan niet de tool-namen. Vraag de gebruiker om de actie te verduidelijken.
- Verzin geen waarden; zoek in de vaste volgorde. Verwijs naar de locatie, niet naar de waarde.
- Waarden die opnieuw gebruikt zullen worden, moeten met toestemming van de gebruiker worden vastgelegd.
- Wat is vastgelegd moet worden opgezocht, niet opnieuw gevraagd. Haal het niet uit het geheugen.
- Vraag naar lege velden in één batch.
Een principe is geen prompt. Een zin in een prompt verwatert naarmate het gesprek groeit. Een principe moet buiten de prompt staan, zoals de lijst, en elke keer worden toegepast wanneer een tool betrokken is.
Opmerking: Tool-selectie wordt niet door code opgevangen. Als het model naar één tool convergeert zonder terug te vragen, en die tool staat op de lijst en heeft de vereiste capaciteit, dan passeert het elke latere fase. Dit blijft een principe en een restrisico.
Code (schendingen hiervan zijn extern zichtbaar)
- Bouw de lijst en tel de items.
- Controleer de aangewezen locatie om te bevestigen dat de waarde daar daadwerkelijk staat.
- Lees de labels en dwing deze af. Koppel goedkeuring aan het
{slot, waarde}paar, zodat de goedkeuring ongeldig wordt als de waarde verandert. - Registreer het oordeel, en laat de uitvoering alleen dit record accepteren. Registreer ook wat is geblokkeerd.
Alles wat de code weet, is het formulier. Welke slots nodig zijn en wat elk label betekent, is data.
Wat blijft er over voor het model?
Het model zoekt waarden op, de code telt wat leeg is, en wat overblijft wordt in het gesprek gevraagd. Alleen het restant gaat naar het gesprek, dus het aantal vragen vermenigvuldigt zich niet.
| Onderdeel | Herkomst |
|---|---|
| Waarde | Lookup, of de gebruiker |
| Slot | De lijst |
| Oordeel | Counting |
| Timing | De woorden van de gebruiker |
De gebruiker maakt het, het model bevestigt het. Als het niet bevestigd kan worden, vindt het gesprek de gemeenschappelijke grond. De tool wordt gematcht vanuit de lijst; wat niet op de lijst staat, kan niet worden gekozen. De stap van het "maken" verdwijnt. Er is geen ruimte meer om te verzinnen.
Het verslag zorgt voor audit en verbetering
De uitvoering begint vanuit een record. Dat record bevat elk antwoord. Welk veld leeg was, wat onjuist was ingevuld, welk verplicht veld niet bestond — er blijft een verslag over van het moment van uitvoering.
- Een veld is leeg omdat de gebruiker het niet zei → Vragen lost dit op.
- Een veld is afwezig omdat de provider het niet heeft opgegeven → Vragen lost dit niet op. Je kunt de gebruiker niet vragen wat de voorwaarden van een tool zijn.
Momenteel landen alle anomalieën bij de ontwikkelaar van de agent. De oorzaak kan een onvolledige tool-definitie zijn. Door een bron aan het lege veld te koppelen, kan die case naar de provider worden gestuurd. De verantwoordelijkheid wordt niet verschoven; de plek waar deze al lag, wordt zichtbaar gemaakt.
Interne regels
Vandaag de dag leven interne regels gedeeltelijk in prompts, gedeeltelijk in branches in tool-wrappers en gedeeltelijk alleen als conventie. Dit maakt het onmogelijk om de correcte werking te bevestigen.
- Het wijzigen van één regel vereist een deployment.
- Je kunt niet vragen welke regels van toepassing waren op een specifieke uitvoering.
- Je kunt niet uitleggen waarom een bepaalde case in de goedkeuringswachtrij terechtkwam.
Zodra de lijst op deze manier is gestructureerd, kan een eigen regel worden toegevoegd als één regel op dezelfde plek. Er is geen aparte code nodig om de regel af te dwingen.
Provider-voorwaarden: een minimaal implementatievoorstel
Er hoeft niets nieuws te worden geschreven aan de provider-zijde. Wat al in de tool-beschrijving staat, wordt simpelweg één regel op de lijst.
[required]— onderworpen aan broncontrole. Als het niet in de status staat, komt het op de lijst van unknowns.[confirm]— een slot dat niet kan worden ingevuld zonder goedkeuring van de gebruiker.[notice]— iets waar de gebruiker vooraf tijdens het gesprek van op de hoogte moet zijn.
De beschrijving is al beschikbaar voor de middleware wanneer de tool-lijst wordt opgehaald. Omdat het vocabulaire vaststaat, is het extraheren van de labels simpelweg string-parsing.
Open vragen
In hoeverre is dit van toepassing? Pas dit alleen toe op onomkeerbare acties en laat 'reads' passeren. Als alles onmiddellijk is, is het timing-slot niet nodig; als er maar één tool is, is het tool-selectie-slot niet nodig. Zelfs als de agent en de tool dezelfde eigenaar hebben, moet er een lijst worden gemaakt.
Is dit niet overbodig zodra modellen beter worden? Dat zou betekenen dat modelprestaties worden gebruikt om ontbrekende informatie in te vullen, wat niet houdbaar is. Deze structuur profiteert juist van verbeteringen in modellen. Het gaat niet om het repareren van het model, maar om het niet hoeven repareren.
Waarom de checklist niet in de prompt zetten en JSON terugvragen? Dat geeft de taak om te bepalen wat er gevraagd moet worden weer terug aan het model. Als het model degene is die oordeelt of een slot leeg is, is er geen manier om zijn rapport te verifiëren wanneer hij zegt dat alles is ingevuld.
Voorkomt dit dat de verkeerde tool wordt gekozen? Tool-selectie zelf staat buiten deze structuur. Het vernauwt de kandidaten en dwingt tot verduidelijking. Een verzonnen tool wordt geblokkeerd omdat deze niet op de lijst staat. Het risico dat er gekozen wordt voor de verkeerde tool uit een groep tools die allemaal de actie kunnen uitvoeren, blijft bestaan.
Wat als het verslag vervalst is? Het scheiden van het oordeel van de uitvoering voorkomt uitvoering zonder oordeel. Het voorkomt echter geen gefabriceerd oordeel.
Bouwen op recente frameworks
Het isoleren van tools en context achter een protocol, en het binden van output aan een schema, zijn mogelijkheden die recentelijk zijn vastgesteld door agent-orchestratie en frameworks zoals LangGraph en MCP. Dit voorstel bouwt daarop voort.
Wat dit voorstel claimt
Dit is geen structuur die is ontworpen voor veiligheid. Het doel is om te weten wat er leeg is; veiligheid volgt daaruit. Een waarde zonder bron kan geen argument worden, een resterend leeg veld stopt de uitvoering, en zonder oordeel is er geen pad naar uitvoering.
Vandaag de dag is de enige vraag bij een incorrecte uitvoering: "Waarom deed het model dat?", en daar is geen antwoord op. Zet de lijst buiten het model, en de vraag verandert: Welk slot was leeg? Welke bron faalde in het produceren van een antwoord? In welke fase stopte het?
De black box opent niet volledig. Waarom die tool werd gekozen, is nog steeds niet zichtbaar. Wat wel zichtbaar wordt, is wat erin ging en wat eruit kwam.
Redeneren is een kracht in gesprekken, maar het wordt een probleem bij uitvoering. In plaats van te vragen "Heb je het echt uitgevoerd?" en alleen de uitkomst te analyseren, moet de autoriteit van het model om inputwaarden te bepalen worden weggenomen, zodat alleen computatie overblijft. Dit is geen techniek om de nauwkeurigheid te verbeteren — het is een voorwaarde om de uitvoering überhaupt geldig te maken.
Groetjes,