Dify-handleidingen: eerste uitgave, stand 20 september 2026

Handleidingen 01, 02, 03, 05, 07, 08 met Zelf kiezen-kaders en Maak hem van jou;
bijlagen ontwerpkaart, ontwerppatronen, AI-tools in het onderwijs; draaiboek workshop
Kennisfestival 23-09-2026; gedeeld bouwscript, extract.py, CC BY-SA 4.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido van Dijk
2026-09-20 20:25:01 +02:00
commit 659e4c7e76
284 changed files with 3944 additions and 0 deletions
@@ -0,0 +1,402 @@
<!--
VOOR CLAUDE CODE
Bron van handleiding 7 (zelfkritiek en poortwachter, vervolg op handleiding 3).
Beelden in beelden/, vastgelegd op 20 september 2026 via de Chrome-extensie op het
sandbox-account "Dify" (vensters 1468x715, 1568x764 en 1512x794; het bouwscript
schaalt op breedte). Beeld 35 is een verkleinde opname (0,6).
Omzetten naar HTML, PDF en Word: python3 build.py
Opmaakafspraken: zie handleiding 1 t/m 3 (genummerde lijst = handelingen, tabel
"Wat je intypt", codeblok = Intypen, blockquote = valkuil, **Zelf kiezen** = groen kader).
De Python-code voor de Poortwachter is bij het bouwen via de browserconsole in de
Monaco-editor gezet (typen met auto-inspringing gaat mis); deelnemers plakken hem
gewoon met Ctrl+V.
Gepubliceerde app (versie 2 van Schoolnieuws): https://udify.app/workflow/jJclFyX9BlteuHYi
-->
# 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 |
---
## 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](beelden/01-uitgangspunt.jpg)
En zo ziet de staart eruit als je klaar bent:
![Het doel: Controleur, Poortwachter, IF/ELSE en twee uitgangen](beelden/27-hele-keten.jpg)
---
## 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](beelden/02-next-step-output.jpg)
3. Klik op de drie puntjes achter Output en kies **Disconnect**. (Niet **Delete**: het blok mag blijven, alleen de lijn gaat weg.)
![Change, Disconnect, Delete](beelden/03-disconnect-menu.jpg)
![Social heeft nu geen volgende stap meer](beelden/04-losgekoppeld.jpg)
### Stap 2. Voeg de Controleur toe
1. Klik bij **NEXT STEP** op **Select next step** en kies **LLM**.
![De lijst met blokken](beelden/05-nodes-lijst.jpg)
![Het nieuwe, lege LLM-blok](beelden/06-llm4-leeg.jpg)
2. **MODEL**: gpt-5-mini. **CONTEXT**: Knowledge Retrieval / result (de schrijfwijzer).
3. 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](beelden/07-controleur-prompt.jpg)
4. Hernoem het blok naar `Controleur`.
![Controleur klaar: context en conceptbericht zijn gekoppeld](beelden/08-controleur-klaar.jpg)
> "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](beelden/09-code-standaard.jpg)
2. 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](beelden/10-code-ingevuld.jpg)
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](beelden/11-invoer-hernoemd.jpg)
2. 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](beelden/12-variabele-kiezen.jpg)
![Alle drie gekoppeld](beelden/13-invoer-gekoppeld.jpg)
3. 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](beelden/14-uitvoer-type.jpg)
4. Hernoem het blok naar `Poortwachter`.
![Poortwachter klaar](beelden/15-poortwachter-klaar.jpg)
> 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](beelden/16-ifelse-leeg.jpg)
2. Klik bij **IF** op **+ Add Condition** en kies **POORTWACHTER / ok**.
![De variabele voor de voorwaarde](beelden/17-conditie-variabele.jpg)
3. Laat de vergelijking op **=** staan en typ bij de waarde `1`.
![De voorwaarde: ok = 1](beelden/18-conditie.jpg)
### Stap 6. Uitgang 1: Goedgekeurd
1. Bij **NEXT STEP** onder **IF**: **Select next step** → **Output**.
![Het nieuwe Output-blok](beelden/19-output2-leeg.jpg)
2. Voeg drie uitvoervariabelen toe:
| Variable name | Set variable |
| --- | --- |
| `website` | **WEBSITE / text** |
| `ouderapp` | **CONTROLEUR / text** |
| `social` | **SOCIAL / text** |
3. Hernoem het blok naar `Goedgekeurd`.
![Goedgekeurd](beelden/20-goedgekeurd.jpg)
### 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](beelden/21-ifelse-else.jpg)
2. 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** |
3. Hernoem het blok naar `Naar de communicatiemedewerker`.
![De tweede uitgang](beelden/22-naar-medewerker.jpg)
> 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](beelden/23-checklist.jpg)
2. Klik in de checklist op **Output**. Het oude blok wordt geselecteerd; het staat verstopt achter Controleur.
![De oude Output, verstopt achter Controleur](beelden/24-oude-output.jpg)
3. Klik in het paneel op de drie puntjes en dan op **Delete**.
4. Controleer dat de checklist leeg is (geen cijfer meer op het icoon).
![Na het hernoemen naar concept_: geen dubbele variabelen meer](beelden/25-concept-variabelen.jpg)
![De nieuwe staart van de workflow](beelden/26-nieuwe-staart.jpg)
---
## 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** |
2. **Start Run**. Na ongeveer een minuut kleurt het pad via **IF** naar **Goedgekeurd** groen.
![Test 1: het pad loopt via IF naar Goedgekeurd](beelden/28-test1-resultaat.jpg)
3. Klik op **DETAIL**: status SUCCESS, doorlooptijd en tokens.
![Detail van de run](beelden/29-test1-detail.jpg)
4. Klik op **TRACING** en klap **POORTWACHTER** open. Onder OUTPUT staat wat de code teruggaf.
![Tracing: elk blok met zijn tijd en tokens](beelden/30-tracing.jpg)
![De Poortwachter: ok 1, "Alle regels in orde."](beelden/31-poortwachter-ok.jpg)
> 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](beelden/32-controleur-aangevuld.jpg)
### 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](beelden/33-test2-invoer.jpg)
2. **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](beelden/34-test2-afgekeurd.jpg)
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](beelden/35-gepubliceerd.jpg)
2. 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](beelden/36-webapp-afgekeurd.jpg)
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.