18 KiB
Les 13 — Docenttekst (Autocue)
Fysieke les — letterlijk voorleesbaar. Slide-nummers tussen [SLIDE N].
Structuur: ±1 uur presenteren → kwartier pauze → ±1,5 uur "Nu jullie"
Voorbereiding — accounts:
- Supabase ✅ bestaat uit Les 11/12 (polderfest-database)
- OpenAI API key ✅ bestaat uit Les 11
- Vercel ✅ bestaat uit Les 11
- GitHub ✅ bestaat
- Open-Meteo (weer-API) — GEEN account/key nodig, gratis voor demos
Voorbereiding — Supabase:
- Tabel
user_favoritesbestaat al uit Les 11/12 — geen nieuwe tabel nodig- Eventueel tussen demos resetten via
supabase-reset-user-favorites.sqlin de zipVoorbereiding — deploy:
- polderfest-with-agent gepushed naar GitHub repo
- Vercel project aangemaakt + env vars gezet (NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY)
- Productie-URL getest in browser (zowel
/als/agent)- Test prompt 3 ("zet in mijn favorieten") en check dat er een rij verschijnt in Supabase
Voorbereiding — presentatie:
- Cursor open in Polderfest-with-agent map (voor code-walkthrough)
- Browser tabs: gedeployde agent-URL, Vercel dashboard, github.com
- Drie demo-prompts copy-paste klaar (onderaan dit document)
- Voor uitgebreide handleiding zie
Les13-Docenttekst.md(normale versie)
BLOK 1 — Welkom + Terugblik tool calling
[SLIDE 1]
Welkom bij Les 13. Vandaag gaan we de Polderfest-app slimmer maken. Niet één tool die data ophaalt, maar een echte agent die meerdere tools achter elkaar kan gebruiken, een eigen plan opstelt, en zelfs een externe API gebruikt om het weer te checken.
We doen dit op de Polderfest-app die jullie al hebben draaien — geen nieuwe app, geen nieuwe context. Alleen één extra route en een bijbehorende UI-pagina.
[SLIDE 2]
Even kort terug naar vorige les. Tool calling. De AI kreeg toegang tot functies, in ons geval searchBands. Een gebruiker stelde een vraag, de AI riep één keer een functie aan, kreeg data terug, gaf antwoord.
Dat werkt prima voor simpele vragen. "Welke bands spelen er op zaterdag?" → searchBands met day=zaterdag → antwoord.
Maar wat als de vraag complex is? Bijvoorbeeld: "Plan een zaterdagavond met indie en techno, geen tijdoverlap, en als het regent alleen onder een dak."
Eén tool-call is dan niet genoeg. Je hebt nodig: bands per genre voor zaterdag, het dag-schedule om overlap te checken, én het weer. En dat moet allemaal worden gecombineerd tot één eindprogramma.
Dat is een agent. Eén stap verder dan tool calling.
[SLIDE 3]
Hier zien jullie het verschil. Maar belangrijk vooraf: er is geen harde lijn tussen tool calling en agents. In de Vercel AI SDK v6 gebruik je voor beide dezelfde syntax. Het verschil zit in hoe je het ontwerpt.
Tool calling. Typisch een vraag van het type "voer deze functie uit". Meestal één tot drie stappen — ook met stopWhen, want stopWhen kunnen we ook in tool calling gebruiken. Jouw prompt stuurt sterk welke volgorde de AI volgt. Per tool gebruik je typisch één bron.
Agent. Vraag van het type "bereik dit doel, kies zelf hoe". Vaak vier tot tien-plus stappen, en het aantal varieert per vraag. AI plant zelf de volgorde. Combineert meerdere bronnen door elkaar — database én externe API én meer — in één antwoord. En de AI reflecteert: hij ziet een tool-resultaat en beslist wat de volgende stap wordt.
Beide kunnen externe APIs aanroepen. Beide gebruiken stopWhen. Het verschil zit in mindset en in hoeveel ruimte je de AI geeft.
In code zie je dat aan twee dingen: een hogere stopWhen-waarde — acht of meer in plaats van twee of drie — en een bredere, opener system prompt waarin je niet stap-voor-stap voorschrijft.
BLOK 2 — Wat is een agent?
[SLIDE 4]
Wanneer voegt een agent écht waarde toe. Want zoals ik net zei: het is geen "wel/niet". Er is een schaal.
Tool calling is genoeg als je weet welke functie nodig is voor de vraag. Bijvoorbeeld een database-zoekopdracht of een API-call. Het antwoord ligt in één bron. Het pad is voorspelbaar — je kunt het in twee of drie tool-calls zelf beschrijven.
Een agent is écht zinvol als de vraag open is. "Plan een dag." "Vergelijk twee opties." "Vind het beste alternatief." "Concludeer hieruit." Dan moet de AI meerdere bronnen combineren, en het pad is onvoorspelbaar. Soms drie stappen, soms zeven. En soms triggert het eerste resultaat een vervolgvraag — "die band is uitverkocht, zoek een alternatief".
Risico's van agents — waarom niet altijd. Ze lopen langer. Meer stappen betekent meer tokens en hogere kosten en hogere latency. Ze zijn lastiger te debuggen door non-determinisme: twee dezelfde vragen kunnen verschillende paden bewandelen. En voor simpele vragen is een agent gewoon overkill — tool calling is sneller én goedkoper.
Pragmatisch advies dat ik vaak geef: start met tool calling. Pas als je merkt dat je system prompt steeds langer wordt om stappen voor te schrijven, schaal je naar agent-niveau. Want dan kan de AI dat beter zelf bepalen dan dat jij het in tekst probeert te beschrijven.
[SLIDE 5]
Hier zien jullie de agent-loop. Lees mee.
Gebruiker stelt een vraag. Die gaat naar de LLM. De LLM kiest: een tool aanroepen, of direct antwoorden? Bij een tool: voer 'm uit, resultaat terug naar de LLM, en de loop herhaalt.
Hij stopt wanneer de stopWhen-conditie waar is. In ons geval stepCountIs(8) — maximaal acht stappen. Of als de LLM zelf besluit "geen tool meer nodig" en gewoon een antwoord geeft.
Soms duurt het twee stappen. Soms zes. De agent beslist.
[SLIDE 6]
Welke stappen nemen we om bij een eindproduct te komen voor onze Polderfest-agent.
Eén: bedenk welke tools de agent nodig heeft. Voor ons: searchBands om bands op te zoeken in Supabase. getStageSchedule om een complete dag op te halen. En getWeather — een externe API call naar Open-Meteo voor het weer.
Twee: schrijf de system prompt. Vertel de agent wat hij is, welke tools beschikbaar zijn, en welke werkwijze hij moet volgen.
Drie: voeg stopWhen toe. Veiligheid — maximaal acht stappen.
Vier: bouw een UI die de tool-calls laat zien. Anders is het magic zonder zicht — voor onderwijs cruciaal.
Vijf: testen met echte vragen.
Dit gaan we zo live zien.
BLOK 3 — Nieuwe AI SDK functies voor agents
[SLIDE 7]
De eerste nieuwe functie kennen jullie al: tool. Dezelfde syntax als Les 12, maar essentieel.
Drie velden. description — wat de AI hierover leest om te beslissen of-ie deze tool wil gebruiken. inputSchema — een Zod-schema dat de AI automatisch invult. En execute — de functie die draait als de tool wordt aangeroepen.
Voor searchBands hebben we genre en day als optionele parameters. De AI bepaalt zelf welke combinatie hij nodig heeft.
[SLIDE 8]
Dit is de kern. stopWhen is wat van tool calling een agent maakt.
Bekijk het code-blok. We voegen één regel toe: stopWhen: stepCountIs(8). Maximaal acht stappen.
Zonder die regel doet de AI één tool-call en stopt. Met die regel mag-ie blijven doorlopen tot acht stappen zijn gehaald of tot-ie zelf besluit klaar te zijn.
Andere stop-condities die je kunt combineren. hasToolCall("finishPlan") — stop als een specifieke tool is aangeroepen. Dat is handig als je de agent dwingt eerst een eindplan te maken voor-ie stopt. Of eigen functies die naar de output kijken.
[SLIDE 9]
Het mooiste van tools: ze hoeven niet alleen je eigen database te zijn. Externe APIs werken net zo.
Belangrijk om eerlijk te zijn: dit kon ook al in Les 12 met tool calling. De execute-functie is gewoon JavaScript — een fetch is altijd al mogelijk geweest. Dit is geen nieuwe agent-feature.
Wat agents wel échte meerwaarde geeft: omdat de loop meerdere stappen mag duren, kan de agent het resultaat van een externe API gebruiken om vervolgens een tweede tool aan te roepen. Dus eerst weer ophalen, dan op basis van dat weer bands zoeken. Die combinatie is wat agents onderscheidt.
Bekijk de getWeather-tool. Beschrijving: weer-forecast voor een festivaldag. Schema: één datum-string. Execute: een fetch naar Open-Meteo.
Open-Meteo is een gratis weer-API. Geen account nodig, geen API-key nodig. Perfect voor demos.
Vuistregel: wat een fetch kan, kan een tool. Stripe-saldo opvragen. GitHub-issues lezen. Wikipedia. Spotify. Alles via HTTP — alles kan een tool zijn.
BLOK 4 — Drie agent-extra's bovenop Les 12
[SLIDE 10]
Drie features die we vandaag bovenop Les 12 zetten. Dit is waar het echt agent-werk wordt.
Eén: prepareStep. Hiermee wissel je per stap van model. Stap nul — dat is de eerste stap, het begin van de loop — krijgt het krachtige model gpt-5.2. Dat doet de planning. Latere stappen, waarin de agent alleen tool-calls uitvoert, gebruiken het lichtere gpt-5-mini. Resultaat: zelfde kwaliteit, significant lagere kosten en latency.
Twee: hasToolCall plus finishPlan. We voegen een speciale tool toe genaamd finishPlan. Die heeft een Zod-schema voor een gestructureerd eindplan — een lijst van items met tijd, band, stage en reden. En we voegen aan onze stopWhen-conditie toe: stop zodra de agent finishPlan heeft aangeroepen. Voordeel: gegarandeerd een nette eind-structuur, geen vrije-vorm-tekst die je moet parsen.
Drie: een write-tool. addToFavorites. Tot nu toe lazen al onze tools alleen data uit Supabase. Met deze tool kan de agent een band toevoegen aan een favorites-tabel. Dat is een gigantische stap — de agent verandert nu de wereld, niet alleen leest hij. Concreet: gebruiker zegt "Zet Band 5 in mijn favorieten", agent roept addToFavorites aan, er staat een rij in Supabase.
Combinatie: agent plant met het krachtige model in stap 0, voert uit met het goedkope model in stap 1-plus, schrijft favorieten naar de DB als de gebruiker dat vraagt, en sluit af met een gestructureerd plan via finishPlan.
Dit is écht agent-werk — niet zomaar tool calling met meer stappen.
BLOK 5 — Roadmap + code-walkthrough
[SLIDE 11]
Dit is de roadmap. Twee kolommen. Links de dingen die we al hebben uit Les 11 en 12 — het tool-pattern, stopWhen, de Supabase-client, en de bestaande tabellen bands en user_favorites. Daar gaan we vandaag niet opnieuw doorheen.
Rechts wat nieuw is. Zes echte agent-features: getWeather voor de externe API, addToFavorites als write-tool, finishPlan voor gestructureerde output, hasToolCall als tweede stop-conditie, prepareStep voor model per stap, en de UI met tool-call rendering.
Voor de komende zes slides geldt: ik open de gedeployde polderfest-with-agent, en in mijn editor. Per slide zie je een zoekterm — STEP N. Daarmee springen we direct naar de juiste plek in de code. Ik leg uit wat er staat. Geen typen.
[SLIDE 12]
STAP 7. getWeather — externe API als tool. Zoek in de editor op STEP 7 in app/api/agent/route.ts.
Dit is een fetch naar Open-Meteo. Gratis, geen account, geen API-key. We sturen lat-lon van Utrecht, een datum, en krijgen temperatuur plus regen-kans terug.
Belangrijk: dit kon ook al in Les 12 met tool calling. Het is niet exclusief voor agents. Wat agents wel doen: ze gebruiken het resultaat van deze tool om een volgende tool te kiezen. Bijvoorbeeld: regenkans hoog → searchBands met stage="Tent".
[SLIDE 13]
STAP 8. addToFavorites — onze eerste write-tool. Zoek op STEP 8.
Hier zien jullie iets nieuws. Tot nu toe deden alle tools alleen reads uit Supabase. Deze schrijft. Twee stappen: eerst zoekt de tool de band op naam — we hebben de band_id nodig als FK. Daarna insert in de bestaande user_favorites tabel met een vaste demo-user.
In productie zou je hier echte auth gebruiken plus RLS uit Les 10 zodat users alleen hun eigen rijen kunnen toevoegen. Voor onze demo hardcoderen we de user.
Dit is écht agent-werk — de agent verandert de wereld.
[SLIDE 14]
STAP 9. finishPlan — structured output. Zoek op STEP 9.
Deze tool heeft een Zod-schema dat een complete plan-structuur dwingt. Een summary plus een lijst items met tijd, band, stage en reden. De agent moet hier zijn eindplan in plaatsen.
Voordeel: in de UI krijgen we geen vrije-vorm-tekst die we moeten parsen, maar een gestructureerd object dat we mooi kunnen renderen als een timeline-kaart. Komt straks bij STAP 13.
[SLIDE 15]
STAP 10. hasToolCall — stop-conditie op signaal. Zoek op STEP 10.
Hier zien jullie hoe we stopWhen combineren. Twee condities in een array. Eerst stepCountIs van acht — onze veiligheid. Tweede: hasToolCall finishPlan — zodra de agent finishPlan heeft aangeroepen stopt de loop direct.
Effect: gegarandeerde nette afsluiting. Geen agent die nog drie nutteloze tool-calls doet na zijn finale plan.
[SLIDE 16]
STAP 11. prepareStep — model per stap. Zoek op STEP 11.
Dit is een mooie. We geven een functie die per stap een model kiest. Stap nul, de eerste stap waarin de agent het probleem begrijpt en zijn plan maakt, krijgt gpt-5-punt-2. Het krachtige model. Stap één en verder gebruiken gpt-5-mini. Goedkoop en snel.
Resultaat: significant lagere kosten en latency, zelfde eindkwaliteit. Want het denkwerk zit in stap nul. De rest is uitvoering.
[SLIDE 17]
STAP 13. UI rendering. Zoek op STEP 13 in app/agent/page.tsx.
Hier zien jullie de truc die het magisch maakt. We lopen door m.parts en herkennen drie types. Een tool-finishPlan rendeer ik als nette plan-kaart met timeline. Een tool-addToFavorites als gele badge "toegevoegd aan favorieten". Andere tool-calls als expandable JSON details.
Zonder deze UI ziet de gebruiker alleen een eindbericht. Met deze UI ziet hij stap-voor-stap denken — en dat is wat het écht agent voelt.
[SLIDE 18]
Tot zo ver de code-walkthrough. Voor wie het visueel wil onthouden: dit is het stappenplan van Polderfest naar Polderfest-met-agent. Tien nummerblokken in twee kolommen. Voor de details: zie Les13-Stap-voor-stap.md.
Nu een live demo van wat dit allemaal samen doet.
BLOK 6 — LIVE DEMO
[SLIDE 19]
Tijd voor de demo. Ik open de gedeployde versie van Polderfest-with-agent in de browser. Jullie zien een chat-interface met de tekst "Polderfest 2027 — Agent" bovenaan. Onderaan een input-veld.
Ik typ de eerste prompt:
Plan een avond met indie en techno voor zaterdag.
Versturen. Jullie zien onderaan een bericht verschijnen "Agent denkt na". En dan klap-voor-klap zien jullie de tool-calls. Eerst searchBands met genre=indie en day=zaterdag. Dan searchBands opnieuw, nu met genre=techno. Dan getStageSchedule voor zaterdag.
En aan het eind: een gepland avondprogramma. Compleet, met tijden, geen overlap, gesorteerd per stage. De agent heeft autonoom vier of vijf stappen gezet en het resultaat samengebracht.
Tweede prompt:
Wat speelt er op zondag en hoe is het weer dan?
Hier zien jullie de externe weer-API in actie. De agent roept getWeather aan voor 2027-07-11. Krijgt temperatuur en regen-kans terug. En koppelt dat aan het schedule.
Derde prompt:
Welke band moet ik NIET missen op vrijdag? Zet hem in mijn favorieten.
Hier wordt het interessant. Er is geen tool die "must-see"-bands teruggeeft. De agent moet creatief combineren — searchBands met day=vrijdag, kijken naar populariteit-velden, en een mening vormen.
Daarna kijken we in de code. Cursor open. app/api/agent/route.ts. Ik wijs aan: de drie tools, de system prompt, de stopWhen.
Dan app/agent/page.tsx. Vooral het stuk dat de tool-calls toont — die details-tags met JSON-output per part.
En als finale: vergelijking met app/api/chat/route.ts van Les 11. Twintig regels system-prompt + alle bands in context versus deze agent met drie tools. "Kijk hoeveel meer kan met agents."
PAUZE
Tijd voor een kwartier pauze. Ik mute mijn microfoon, koffie halen. Tot zo.
BLOK 7 — Nu jullie
[SLIDE 20]
Welkom terug. Nu jullie beurt.
Doel: bouw zelf een Polderfest-agent. Vanaf de Polderfest-app die je al hebt uit Les 12, of vanaf de starter zip uit lesbestanden/.
In de lesbestanden-map staan drie bestanden. polderfest-original.zip — startpunt. polderfest-with-agent.zip — referentie als je vastloopt, mag je gerust openen. En Les13-Stap-voor-stap.md — elf stappen, volg ze één voor één.
Werk in jullie eigen tempo. Test met de drie voorbeeld-prompts in de browser. En als alles werkt: pushen naar Vercel — vergeet de environment variables niet, Vercel kent jullie keys nog niet.
Deel je productie-URL in de chat als je klaar bent. Ik kom bij iedereen langs.
Vragen? Hand op, of roep me.
BLOK 8 — Afsluiting
[SLIDE 21]
Bijna klaar. Korte samenvatting.
Het verschil tussen tool calling en een agent zit in één regel code: stopWhen. Zonder is het tool calling, met is het een agent.
Drie nieuwe AI SDK functies vandaag. Eén: tool om een tool te definiëren met description, inputSchema en execute. Twee: stepCountIs om een maximaal aantal stappen te stellen. Drie: multi-step loops via streamText.
Externe APIs als tool. Open-Meteo voor weer, geen key nodig. Vuistregel: wat een fetch kan, kan een tool.
En we hebben de Polderfest-app uitgebreid. Van een chat met alle bands in de context, naar een echte agent die zelfstandig data verzamelt, externe APIs gebruikt, en eigen plannen opstelt.
Volgende les is Les 14. Externe APIs in diepte, samen met Cursor agents en Vercel deploys met preview deployments en GitHub Actions. Belangrijk om je leerlijn af te ronden naar productie.
Vragen?
DRIE DEMO-PROMPTS — copy-paste tijdens demo
Prompt 1 — basis multi-step
Plan een avond met indie en techno voor zaterdag.
Prompt 2 — externe API gebruiken
Wat speelt er op zondag en hoe is het weer dan?
Prompt 3 — creatief combineren
Welke band moet ik NIET missen op vrijdag? Zet hem in mijn favorieten.
VEELVOORKOMENDE FOUTEN — voor mezelf
| Probleem | Oplossing |
|---|---|
| Vercel kent env vars niet | Add in Vercel → Settings → Environment Variables, redeploy |
| Agent stopt na 1 tool-call | stopWhen: stepCountIs(8) toegevoegd? |
| Tool wordt nooit aangeroepen | Description te vaag — herschrijf in heldere taal |
| Open-Meteo geeft niks terug | Check ISO datum-format (YYYY-MM-DD) |
| UI toont geen tool-calls | Check m.parts.map — zoek op p.type.startsWith("tool-") |
| Supabase fout in agent-route | SUPABASE_SERVICE_ROLE_KEY in .env.local |
| Hydration error op /agent | "use client" bovenaan page.tsx |