Files
dify-handleidingen/07-schoolnieuws-met-controle/handleiding-dify-schoolnieuws-met-controle.md

23 KiB

Schoolnieuws met controle: zelfkritiek en een poortwachter

Handleiding 7 bij de workshop AI Agents
LeX Consultancy B.V. · 20 september 2026

In handleiding 3 bouwde je Schoolnieuws: één kernboodschap wordt een bericht voor website, ouderapp en sociale media. De teksten waren goed, maar ze gingen ongecontroleerd naar buiten. Deze handleiding voegt twee dingen toe die in de bijlage Ontwerppatronen patroon 4 en 5 heten:

Toevoeging Patroon Wat het doet
Controleur (LLM) Zelfkritiek Leest het ouderappbericht nog eens tegen de schrijfwijzer en verbetert het
Poortwachter (Code) plus IF/ELSE Poortwachter Controleert harde regels met code: woordaantal, verboden woorden, hashtag, ontbrekende informatie. Klopt alles, dan naar buiten; anders naar de communicatiemedewerker mét de redenen

Het verschil tussen die twee is de kern van deze handleiding. De Controleur is een model dat een model nakijkt: goed voor vorm en toon, maar het kan zichzelf overtuigen. De Poortwachter is zes regels Python die niet te overtuigen zijn: 81 woorden is te veel, punt. Samen leveren ze wat een communicatiemedewerker wil: minder nakijkwerk, en zekerheid dat de regels die er echt toe doen ook echt gelden.

Deze handleiding volgt de cloudversie van Dify van 20 september 2026. Wijkt je scherm af, volg dan wat je ziet.

Zo lees je deze handleiding

Vorm Betekenis
1. 2. 3. Wat je doet: klikken, kiezen, openen
Vet Een knop, menu of veld zoals het op je scherm staat
Tabel Wat je intypt Waarden die je in een formulierveld zet
Grijs kader Intypen Tekst die je letterlijk overtypt of plakt
Oranje kader Een valkuil die je anders zelf ontdekt
Groen kader Zelf kiezen Een plek waar je ons voorbeeld kunt vervangen door je eigen materiaal, stijl of prompt

De ontwerpkaart van deze app

Voordat we gingen klikken, is deze kaart ingevuld (de lege kaart staat in de bijlage Ontwerpkaart). Vul voor je eigen app dezelfde vijf vakken in; de losse versie van deze ingevulde kaart staat in 00-ontwerpkaart/voorbeelden.

1. Voor wie 2. Wat gaat erin
De communicatiemedewerker die elk bericht drie keer moet schrijven (website, ouderapp, social) en die geen tijd heeft om elke versie langs de schrijfwijzer te leggen. Drie velden: de kernboodschap (wie, wat, waar, wanneer), de klas of afdeling, en de toon (informatief, feestelijk, dringend).
3. Wat komt eruit 4. Waar moet hij zich aan houden
Bij goedkeuring: drie versies klaar om te plaatsen. Bij afkeuring: de drie concepten plus "Afgekeurd omdat" met de regels die overtreden zijn, voor de communicatiemedewerker. De schrijfwijzer uit de kennisbank; de Controleur (tweede LLM) herschrijft de ouderapp-versie; de Poortwachter (Code + IF/ELSE) meet woordaantal, verboden woorden, [INVULLEN] en de hashtag. Wat niet door de poort komt, gaat niet naar buiten.

5. Waaraan zie je dat het werkt

Test Wat gaat erin Wat moet eruit komen
1 Compleet bericht over de sportdag, feestelijk Goedgekeurd, drie versies binnen de woordlimieten, met #Voorbeeldcollege
2 Bericht zonder datum Afgekeurd: bevat [INVULLEN]
3 (de lastige) Bericht met "gelieve" en "z.s.m." Afgekeurd met de twee verboden woorden benoemd

Voorbereiding

  • De workflow Schoolnieuws uit handleiding 3 staat op je account en werkt.
  • Je weet wat een LLM-blok en een Output-blok zijn (handleiding 1 en 3).
  • Je hoeft niet te kunnen programmeren. De code plak je; wat hij doet, staat ernaast uitgelegd.

Zo ziet Schoolnieuws eruit voordat je begint:

Uitgangspunt: de workflow uit handleiding 3

En zo ziet de staart eruit als je klaar bent:

Het doel: Controleur, Poortwachter, IF/ELSE en twee uitgangen


Deel A. De Controleur (zelfkritiek)

Stap 1. Maak de Output los van Social

De nieuwe blokken komen tussen Social en Output. Je koppelt Output daarom eerst los.

  1. Open Schoolnieuws in Studio en klik op het blok Social.
  2. Scroll in het rechterpaneel naar NEXT STEP. Daar staat Output.

Next Step van Social: Output

  1. Klik op de drie puntjes achter Output en kies Disconnect. (Niet Delete: het blok mag blijven, alleen de lijn gaat weg.)

Change, Disconnect, Delete

Social heeft nu geen volgende stap meer

Stap 2. Voeg de Controleur toe

  1. Klik bij NEXT STEP op Select next step en kies LLM.

De lijst met blokken

Het nieuwe, lege LLM-blok

  1. MODEL: gpt-5-mini. CONTEXT: Knowledge Retrieval / result (de schrijfwijzer).
  2. Plak in SYSTEM de prompt hieronder. Bij {Context} typ je een schuine streep en kies je Context; bij {Ouderapp/text} kies je onder OUDERAPP het item text.
Je bent de controleur van Het Voorbeeldcollege. Hieronder staat een conceptbericht voor de ouderapp. Beoordeel het op deze punten uit de schrijfwijzer: maximaal 80 woorden; ouders worden aangesproken met u; één boodschap, één datum en één actie; geen afkortingen en geen woorden uit de lijst te vermijden woorden; geen namen van leerlingen; taalniveau B1 (korte zinnen, gewone woorden).

Werk in twee stappen. Stap 1: noem kort wat niet klopt (of schrijf: niets). Stap 2: geef de verbeterde versie. Verzin geen feiten; wat niet in het concept staat, blijft [INVULLEN]. Haal geen feiten, data of tijden weg die in het concept staan; een uiterste datum om aan te melden hoort bij de actie en blijft staan. Verander cijfers niet in woorden.

Geef als antwoord ALLEEN de verbeterde tekst, zonder stap 1, zonder kop en zonder uitleg. Is het concept al goed, geef het dan ongewijzigd terug.

Schrijfwijzer: {Context}

Conceptbericht: {Ouderapp/text}

De prompt, met het menu na een schuine streep

  1. Hernoem het blok naar Controleur.

Controleur klaar: context en conceptbericht zijn gekoppeld

"Werk in twee stappen, maar geef alleen stap 2." Dat is geen tegenstrijdigheid maar een truc: het model beoordeelt eerst (dat verbetert het resultaat) en je krijgt toch schone tekst terug die je direct kunt doorgeven. Laat je stap 1 in het antwoord staan, dan komt die uitleg ook in de ouderapp terecht.

In onze eerste test deed de Controleur precies wat we vroegen, en dat was te veel: "één datum" las hij als "haal de aanmelddatum weg", en "klas 2" werd "klas twee". Daarom staan de twee zinnen over feiten en cijfers in de prompt. Zelfkritiek verbetert vorm; wat er inhoudelijk mag veranderen, moet jij begrenzen.

Zelf kiezen: wat de Controleur nakijkt. De eerste alinea van de prompt is jullie checklist. Wil je ook controleren op "staat er een contactmogelijkheid in"? Of op de toon per kanaal? Zet het erbij. Wil je de Controleur ook op het websitebericht zetten? Kopieer het blok (drie puntjes op het blok, Duplicate), koppel Website/text als conceptbericht en pas de regels aan (200 woorden, kop van acht woorden).


Deel B. De Poortwachter (code)

Stap 3. Voeg een Code-blok toe

  1. Bij Controleur: NEXT STEP → Select next step → onder Transform: Code.

Het Code-blok met voorbeeldcode

  1. Klik in de editor, selecteer alles (Ctrl+A) en plak de code hieronder.
def main(website: str, ouderapp: str, social: str) -> dict:
    redenen = []
    verboden = ["middels", "omtrent", "z.s.m.", "d.m.v.", " a.s.", "gelieve", "ouder(s)/verzorger(s)"]
    teksten = (("website", website, 230), ("ouderapp", ouderapp, 90), ("social", social, 70))
    for naam, tekst, maximum in teksten:
        aantal = len(tekst.split())
        if aantal > maximum:
            redenen.append(f"{naam}: {aantal} woorden, maximaal {maximum}")
        if "[INVULLEN]" in tekst:
            redenen.append(f"{naam}: bevat [INVULLEN], er ontbreekt informatie")
        for woord in verboden:
            if woord in tekst.lower():
                redenen.append(f"{naam}: bevat het te vermijden woord '{woord.strip()}'")
    if "#voorbeeldcollege" not in social.lower():
        redenen.append("social: #Voorbeeldcollege ontbreekt")
    return {
        "ok": 0 if redenen else 1,
        "redenen": "\n".join(redenen) if redenen else "Alle regels in orde.",
    }

De code staat erin

Wat de code doet, regel voor regel in gewone taal:

Regel Betekenis
verboden = [...] De lijst woorden die nooit in een tekst mogen. Dit is de lijst uit de schrijfwijzer, hier hard gemaakt
teksten = (...) De drie teksten met hun maximum in woorden. De maxima liggen iets boven de schrijfwijzer (200, 80, 60), omdat de kop en het label WEBSITE meetellen
if aantal > maximum Te lang: noteer een reden
if "[INVULLEN]" in tekst Het model heeft iets niet geweten: noteer een reden. Dit is de belangrijkste regel: een bericht met een gat gaat nooit naar buiten
for woord in verboden Staat een verboden woord in de tekst: noteer een reden
if "#voorbeeldcollege" not in ... Het socialbericht moet de schoolhashtag hebben
return {...} Geef twee dingen terug: ok (1 = goed, 0 = fout) en redenen (de lijst, of "Alle regels in orde.")

Let op de inspringing: in Python telt elke spatie aan het begin van een regel. Plakken met Ctrl+V gaat goed. Overtypen gaat bijna altijd mis, doe dat niet.

Stap 4. Koppel de invoer en de uitvoer

  1. Hernoem bij INPUT VARIABLES arg1 naar website en arg2 naar ouderapp. Klik op + voor een derde variabele en noem die social. De namen moeten precies gelijk zijn aan de namen in de eerste regel van de code.

Invoervariabelen hernoemd, derde toegevoegd

  1. Klik per variabele op Set variable en kies:
Variabele Kies
website WEBSITE / text
ouderapp CONTROLEUR / text (de verbeterde versie, niet de ruwe)
social SOCIAL / text

De variabelekiezer

Alle drie gekoppeld

  1. Bij OUTPUT VARIABLES: hernoem result naar ok en zet het type op Number. Klik op + en voeg redenen toe, type String.

Het type kiezen: Number

  1. Hernoem het blok naar Poortwachter.

Poortwachter klaar

De uitvoernamen (ok, redenen) moeten letterlijk overeenkomen met de namen in de return-regel van de code. Eén letter anders en de workflow stopt met een foutmelding over een ontbrekende uitvoer.

Zelf kiezen: de harde regels. Alles wat je met zekerheid kunt controleren, hoort hier en niet in een prompt: lengte, verboden woorden, verplichte onderdelen (hashtag, contactregel, datum in de toekomst), geen e-mailadressen van personen, geen telefoonnummers behalve dat van de receptie. Vraag je communicatiemedewerker: "Welke fout mag nooit meer voorkomen?" Dat is je eerste regel.


Deel C. De poort: IF/ELSE en twee uitgangen

Stap 5. IF/ELSE

  1. Bij Poortwachter: Select next step → onder Logic: IF/ELSE.

Het lege IF/ELSE-blok

  1. Klik bij IF op + Add Condition en kies POORTWACHTER / ok.

De variabele voor de voorwaarde

  1. Laat de vergelijking op = staan en typ bij de waarde 1.

De voorwaarde: ok = 1

Stap 6. Uitgang 1: Goedgekeurd

  1. Bij NEXT STEP onder IF: Select next step → Output.

Het nieuwe Output-blok

  1. Voeg drie uitvoervariabelen toe:
Variable name Set variable
website WEBSITE / text
ouderapp CONTROLEUR / text
social SOCIAL / text
  1. Hernoem het blok naar Goedgekeurd.

Goedgekeurd

Stap 7. Uitgang 2: naar de communicatiemedewerker

  1. Klik op het blok IF/ELSE. Onder ELSE staat nog Select next step; kies Output.

IF heeft Goedgekeurd, ELSE nog niets

  1. Voeg vier uitvoervariabelen toe. De redenen komen bovenaan, zodat de medewerker meteen ziet wat er mis is.
Variable name Set variable
afgekeurd_omdat POORTWACHTER / redenen
concept_website WEBSITE / text
concept_ouderapp CONTROLEUR / text
concept_social SOCIAL / text
  1. Hernoem het blok naar Naar de communicatiemedewerker.

De tweede uitgang

Twee Output-blokken mogen geen gelijknamige variabelen hebben. Noem je ze in beide website, dan zet Dify een oranje "Dubbele variabele" in de checklist en kun je niet publiceren. Vandaar concept_ in de tweede uitgang.

Stap 8. Ruim de oude Output op

  1. Klik rechtsboven op het checklist-icoon (naast Test Run). Je ziet welke blokken nog niet kloppen.

De checklist: de oude Output is nergens aan verbonden

  1. Klik in de checklist op Output. Het oude blok wordt geselecteerd; het staat verstopt achter Controleur.

De oude Output, verstopt achter Controleur

  1. Klik in het paneel op de drie puntjes en dan op Delete.
  2. Controleer dat de checklist leeg is (geen cijfer meer op het icoon).

Na het hernoemen naar concept_: geen dubbele variabelen meer

De nieuwe staart van de workflow


Deel D. Testen: één keer goed, één keer fout

Een poortwachter test je altijd twee kanten op. Alleen de goede kant testen bewijst niets.

Stap 9. Test 1: een compleet bericht

  1. Test Run. Vul in:
Veld op het scherm Wat je intypt
Wat is er gebeurd... Op donderdag 8 oktober om 19.30 uur is er een ouderavond voor klas 2 in de aula. Mentoren vertellen over de profielkeuze en het toetsweekrooster. Ouders kunnen zich tot 5 oktober aanmelden via het ouderportaal. Er is koffie en thee vanaf 19.15 uur.
Voor welke klas of afdeling? klas 2
Welke toon past bij dit bericht? informatief
  1. Start Run. Na ongeveer een minuut kleurt het pad via IF naar Goedgekeurd groen.

Test 1: het pad loopt via IF naar Goedgekeurd

  1. Klik op DETAIL: status SUCCESS, doorlooptijd en tokens.

Detail van de run

  1. Klik op TRACING en klap POORTWACHTER open. Onder OUTPUT staat wat de code teruggaf.

Tracing: elk blok met zijn tijd en tokens

De Poortwachter: ok 1, "Alle regels in orde."

Tracing is je vriend. Bij elke vraag "waarom kwam dit eruit?" open je hier het blok en zie je precies wat erin ging en wat eruit kwam. Dat is ook het scherm waarop je zag dat de Controleur de aanmelddatum had weggehaald (zie het oranje kader in stap 2).

De aangevulde prompt van de Controleur na test 1

Stap 10. Test 2: een bericht met gaten

  1. Test Run opnieuw, nu met een boodschap zonder datum, zonder tijd en met een afkorting:
Veld op het scherm Wat je intypt
Wat is er gebeurd... Binnenkort is er weer een ouderavond voor de brugklassen. De mentoren vertellen dan hoe het gaat en wat er komend jaar gebeurt. Ouders moeten zich z.s.m. aanmelden.
Voor welke klas of afdeling? brugklassen
Welke toon past bij dit bericht? informatief

Test 2: de invoer

  1. Start Run. Nu loopt het pad via ELSE naar Naar de communicatiemedewerker, en bovenaan het resultaat staan de redenen.

Test 2: afgekeurd, met vier redenen

Lees de redenen: alle drie de teksten bevatten [INVULLEN] (de modellen wisten de datum niet en hebben hem netjes niet verzonnen), en in het socialbericht staat "z.s.m.". Dat laatste is leerzaam: de prompt van Social vroeg om de schrijfwijzer te volgen, en toch glipte de afkorting uit de kernboodschap erdoorheen. Een prompt vraagt; de poortwachter dwingt af.

Stap 11. Publiceer

  1. Publish → Publish Update. Dify maakt versie 2 van de app; met Naam geven kun je een versie een naam geven, en via het klokje rechtsboven kun je altijd terug naar versie 1.

Gepubliceerd als versie 2

  1. Open de webapp en herhaal test 2. De collega ziet de redenen bovenaan en daaronder de concepten om aan te vullen.

De webapp: afgekeurd, met de redenen en de concepten

De link is dezelfde gebleven: https://udify.app/workflow/jJclFyX9BlteuHYi


Controleren of het gelukt is

  • De checklist rechtsboven toont geen cijfer
  • Test 1 eindigt in Goedgekeurd, test 2 in Naar de communicatiemedewerker
  • In TRACING geeft Poortwachter bij test 1 ok: 1 en bij test 2 ok: 0 met minstens één reden
  • Het ouderappbericht in Goedgekeurd komt van Controleur (te zien in de Output-instellingen), niet van Ouderapp
  • De webapp toont bij een afgekeurd bericht de redenen bovenaan

Als het misgaat

Wat je ziet Wat er aan de hand is
Code-blok: fout over IndentationError of SyntaxError De inspringing is beschadigd. Selecteer alles, verwijder, plak opnieuw
Code-blok: fout over een ontbrekende uitvoervariabele De namen bij OUTPUT VARIABLES wijken af van ok en redenen in de return-regel
Code-blok: main() missing argument Een invoervariabele heet anders dan in de eerste regel van de code, of is niet gekoppeld
IF/ELSE gaat altijd naar ELSE Het type van ok staat op String in plaats van Number, of je vergelijkt met "1" in plaats van 1
Checklist: "Dubbele variabele van de outputnode" Twee Output-blokken gebruiken dezelfde variabelenaam. Hernoem er één (stap 7)
Checklist: "This step is not connected to anything" Het oude Output-blok bestaat nog. Verwijder het (stap 8)
De Controleur haalt informatie weg of verandert cijfers De prompt begrenst niet wat inhoudelijk mag veranderen. Zie de twee zinnen in stap 2
Goedgekeurd toont het ruwe ouderappbericht De variabele ouderapp in Goedgekeurd wijst naar Ouderapp/text in plaats van Controleur/text
De run duurt meer dan twee minuten Vier LLM-blokken achter elkaar; normaal is 60 tot 90 seconden. Duurt het langer, kijk in Tracing welk blok blijft hangen

Beheer en kosten

  • Eén run kost nu vier modelaanroepen (Website, Ouderapp, Social, Controleur) en zo'n 7.500 tokens; met een eigen OpenAI-sleutel ongeveer anderhalve cent, op Dify-credits ongeveer 13. Het Code-blok en IF/ELSE kosten niets. Een sandbox-account (200 credits) haalt daarmee zo'n vijftien runs; een Professional-account (5.000 credits per maand) is voor een team ruim voldoende.
  • De verboden lijst staat op twee plekken: in de schrijfwijzer (voor de modellen) en in de code (voor de poort). Verandert de schrijfwijzer, pas dan ook de code aan. Wie dat vergeet, krijgt afkeuringen die de modellen niet begrijpen.
  • Versies. Elke Publish Update is een nieuwe versie. Gaat een aanpassing mis, dan zet je via het klokje rechtsboven de vorige versie terug zonder opnieuw te bouwen.
  • Logs tonen ook welke berichten zijn afgekeurd en waarom. Dat is precies de informatie die je nodig hebt om de prompts van Website, Ouderapp en Social te verbeteren: elke reden die vaak voorkomt, is een zin die in een prompt ontbreekt.

Maak hem van jou

Van makkelijk naar moeilijk.

Aanpassing Waar Moeilijkheid Wat je ervoor terugkrijgt
Andere verboden woorden Code, regel verboden makkelijk De echte lijst van jullie schrijfwijzer wordt afgedwongen
Andere woordlimieten Code, regel teksten makkelijk Limieten die bij jullie kanalen passen
Extra controlepunt voor de Controleur Stap 2, eerste alinea van de prompt makkelijk Meer nakijkwerk van je bord
Een Controleur voor het websitebericht Duplicate van het blok, andere invoer en regels gemiddeld Ook de langste tekst nagekeken
Een regel "datum moet in de toekomst liggen" Code, met datetime gemiddeld Geen berichten meer over gisteren
Een derde uitgang: "twijfel" voor kleine overtredingen Tweede voorwaarde in IF/ELSE (ELIF) en een tweede teller in de code gemiddeld Kleine dingen automatisch door, grote naar een mens
Een mens in de lus: het bericht pas plaatsen na een klik Blok Human Input vóór Goedgekeurd moeilijk De eerlijkste poortwachter die er is
Zelfkritiek in een lus tot de poort open gaat (maximaal twee rondes) Blok Loop rond Controleur en Poortwachter moeilijk Minder afkeuringen, wel dubbele kosten

Drie opdrachten

  1. Vul de lijst. Vraag je communicatieteam naar de vijf woorden of formuleringen die zij het vaakst wegstrepen. Zet ze in verboden en draai test 1 en test 2 opnieuw. Wordt test 1 nu ook afgekeurd? Dan is je lijst te breed (een woord als "even" komt overal voor) en moet je preciezer zijn.
  2. Breek de poort. Schrijf een kernboodschap die door de poort komt maar toch fout is: een verkeerde datum, een verzonnen naam van een leerling, een toon die niet past. Wat vangt de Controleur, wat vangt de code, en wat vangt niemand? Voor dat laatste schrijf je een nieuwe regel, of je besluit dat een mens dat blijft doen.
  3. Meet het. Draai tien echte berichten van de afgelopen maand door de app. Tel: hoeveel kwamen er direct door, hoeveel werden afgekeurd, en hoeveel van de afkeuringen waren terecht? Die drie getallen zijn je gesprek met de directie over of dit de moeite waard is.

Checklist voordat je eigen materiaal gebruikt

  • De verboden lijst en de limieten in de code komen overeen met de schrijfwijzer in de kennisbank
  • Je hebt beide kanten getest: een bericht dat door de poort moet, en een dat moet worden tegengehouden
  • Er is afgesproken wie de afgekeurde berichten oppakt en binnen hoeveel tijd
  • De kernboodschappen die collega's invoeren bevatten geen namen van leerlingen; de poort controleert daar niet op
  • Iemand leest ook goedgekeurde berichten steekproefsgewijs na; de poort controleert vorm, geen waarheid
  • Je hebt de vorige versie van de app nog (versiegeschiedenis), voor het geval de nieuwe iets breekt

En verder

Je hebt nu alle vijf de patronen uit de bijlage Ontwerppatronen in handen: één aanroep (handleiding 1), redeneren met gereedschap (2 en 3), plannen en uitvoeren (3 en 4), zelfkritiek en een poortwachter (deze). Handleiding 6, de lesmateriaal-agent in de Agent Console, zet ze alle vijf tegelijk in.