# Les 13 — Agents (Klas A) > **Deel 3: AI Development** (Les 11–16) > **Lesvorm:** fysiek, demo-driven > **Structuur:** ±1 uur presenteren → pauze → ±1,5 uur zelf bouwen --- ## Blok-structuur | Blok | Onderwerp | Slides | |------|-----------|--------| | 1 | Welkom + Terugblik tool calling | 1–3 | | 2 | Wat is een agent? | 4–6 | | 3 | AI SDK basics: tool, stopWhen, externe API | 7–9 | | 4 | Drie agent-extra's: prepareStep + hasToolCall/finishPlan + write-tool | 10 | | 5 | Stappenplan Polderfest → Polderfest-met-agent | 11 | | 6 | LIVE DEMO — gedeployde Polderfest-agent | 12 | | – | ☕ Pauze | – | | 7 | Nu jullie — zelf bouwen | 13 | | 8 | Afsluiting | 14 | --- ## BLOK 1 — Welkom + Terugblik tool calling ### Slide 1: Title **Les 13 — Agents** Subtitle: Polderfest krijgt brains — multi-step tools + externe API --- ### Slide 2: Wat hebben we vorige les gedaan? **Tool calling (Les 12):** - AI kreeg toegang tot tools (functies) - Eén tool per call: bv. `searchBands(genre)` - Goed voor: "ik weet welke functie ik nodig heb, voer 'm uit" - We hebben dit gebouwd in de Polderfest-app — onze chat zocht in Supabase **Maar:** wat als de vraag complex is en meerdere stappen nodig heeft? Voorbeeld: *"Plan een zaterdagavond met indie + techno, geen overlap, alleen onder een dak als het regent."* Eén tool-call is niet genoeg. Je hebt nodig: dag-schedule + bands per genre + weer. En ze moeten worden gecombineerd. **Dat is een agent.** --- ### Slide 3: Tool calling vs Agent — een continuüm **Belangrijk:** er is geen harde lijn. In AI SDK v6 gebruik je voor beide dezelfde syntax (`streamText`, `tool()`, `stopWhen`). Het verschil zit in **hoe je het ontwerpt**. | | Tool calling (Les 12) | Agent (Les 13) | |---|----------------------|----------------| | Vraag-type | "Voer deze functie uit" | "Bereik dit doel — kies zelf hoe" | | Aantal stappen | Meestal 1–3 (ook met `stopWhen`) | Vaak 4–10+, variabel | | Wie kiest de volgorde | Jouw prompt stuurt sterk | AI plant zelf, autonomer | | Combineren van bronnen | Per tool één bron | Meerdere bronnen door elkaar (DB + externe API + …) | | Reflectie / bijsturen | Nee — direct antwoord | AI checkt resultaat, beslist volgende stap | **Beide kunnen externe APIs aanroepen** — `execute()` is gewoon JavaScript, een `fetch` is prima. **Agent ≠ aparte API**, agent = mindset: "geef AI een doel + tools, laat 'm autonomer beslissen". In code uit zich dat in hogere `stopWhen` waardes (8+ ipv 2-3) en bredere, meer open system prompts. --- ## BLOK 2 — Wat is een agent? ### Slide 4: Wanneer voegt een agent écht waarde toe? **Tool calling is genoeg als:** - Je weet welke functie nodig is (DB-zoekopdracht, API-call) - Het antwoord ligt in één bron - Het pad is voorspelbaar — je kunt het zelf in 2-3 tool-calls beschrijven **Een agent is écht zinvol als:** - De vraag is open ("plan", "vind het beste", "vergelijk en concludeer") - AI moet meerdere bronnen combineren in één antwoord - Het pad is onvoorspelbaar — soms 3 stappen, soms 7 - Eerste resultaat triggert vervolgvragen ("die band is uitverkocht — zoek alternatief") **Risico's van agents (waarom niet altijd):** - Lopen langer — meer tokens, hogere kosten - Moeilijker te debuggen door non-determinisme - Voor simpele vragen overkill — gewone tool calling is sneller én goedkoper **Pragmatisch advies:** start met tool calling. Pas op naar agent-niveau als je merkt dat je system prompt steeds langer wordt om "stappen" voor te schrijven — dan kan AI dat beter zelf bepalen. --- ### Slide 5: Hoe ziet de agent-loop eruit? ``` ┌───────────────────────────────────────┐ │ Gebruiker stelt een vraag │ └─────────────┬─────────────────────────┘ │ ▼ ┌──────────────┐ ┌──▶│ LLM │ → kies een tool of geef antwoord │ └──────┬───────┘ │ │ │ ▼ │ ┌──────────────┐ │ │ Voer tool │ → bv. searchBands of getWeather │ │ uit │ │ └──────┬───────┘ │ │ │ ▼ │ ┌──────────────┐ │ │ Resultaat │ → terug naar LLM │ └──────┬───────┘ └──────────┘ Stopt wanneer: stopWhen-conditie waar wordt (bv. stepCountIs(8) of geen tool-call meer) ``` Dit gaat door — soms 2 stappen, soms 6 — tot de agent klaar is. --- ### Slide 6: Stappen om bij een eindproduct te komen Voor de Polderfest-agent: 1. **Bedenk de tools** — welke acties heeft de agent nodig? - `searchBands(genre, day)` — Supabase - `getStageSchedule(day)` — Supabase - `getWeather(date)` — externe API (Open-Meteo) 2. **Schrijf de system prompt** — vertel de agent wat hij is, welke tools, welke werkwijze 3. **Voeg `stopWhen` toe** — veiligheid (`stepCountIs(8)`) 4. **Bouw een UI** — laat de tool-calls zien, anders is het magic zonder zicht 5. **Test met echte vragen** — "Plan een avond met...", "Welke band op...?" We gaan dit zo live zien. --- ## BLOK 3 — Nieuwe AI SDK functies voor agents ### Slide 7: `tool({ description, inputSchema, execute })` Bekend uit Les 12, maar essentieel: ```typescript import { tool } from "ai"; import { z } from "zod"; searchBands: tool({ description: "Zoek bands op genre en/of dag.", inputSchema: z.object({ genre: z.string().optional(), day: z.enum(["vrijdag", "zaterdag", "zondag"]).optional(), }), execute: async ({ genre, day }) => { // Supabase query return data; }, }), ``` - **description** — wat de AI hierover leest om te beslissen - **inputSchema** — Zod-schema, AI vult dit automatisch in - **execute** — wat er gebeurt als de tool wordt aangeroepen --- ### Slide 8: `stopWhen` — de agent-knop Dit is wat een agent maakt: ```typescript import { stepCountIs } from "ai"; streamText({ model: openai("gpt-5.2"), messages, tools: { ... }, stopWhen: stepCountIs(8), // 👈 dit }); ``` Zonder `stopWhen`: AI doet één tool-call en stopt. Met `stopWhen`: AI loopt door tot conditie waar is — een echte agent-loop. Andere stop-condities die je kunt combineren: - `hasToolCall("finishPlan")` — stop als specifieke tool is aangeroepen - Eigen functies die op output letten --- ### Slide 9: Externe API als tool Tools hoeven niet alleen je eigen DB te zijn. Externe APIs werken net zo: ```typescript getWeather: tool({ description: "Weer-forecast voor een festivaldag.", inputSchema: z.object({ date: z.string() }), execute: async ({ date }) => { const res = await fetch( `https://api.open-meteo.com/v1/forecast?...&start_date=${date}` ); const data = await res.json(); return { temperatureMaxC: data.daily.temperature_2m_max[0], rainChancePercent: data.daily.precipitation_probability_max[0], }; }, }), ``` Open-Meteo: gratis, geen API key. Perfect voor demos. **Vuistregel:** wat een fetch kan, kan een tool. Stripe-saldo opvragen? Tool. GitHub-issues lezen? Tool. Wikipedia? Tool. Externe APIs konden ook met tool calling in Les 12 — dit is niet nieuw. Het verschil bij agents: ze gebruiken vaker **meerdere bronnen door elkaar** in één antwoord (DB + externe API combineren), omdat ze meer stappen mogen zetten. --- ## BLOK 4 — Van Polderfest naar Polderfest-met-agent ### Slide 10: De stappen die we gaan zien In de demo straks doen we (en jullie straks ook): 1. **Polderfest-original** uitpakken (Les 12 versie) 2. Nieuwe route `app/api/agent/route.ts` aanmaken 3. Eerste tool toevoegen: `searchBands` (Supabase) 4. `stopWhen: stepCountIs(8)` toevoegen 5. Tweede tool: `getStageSchedule` 6. Derde tool: `getWeather` (externe API) 7. System prompt schrijven 8. UI-pagina `app/agent/page.tsx` met tool-call-weergave 9. Testen in browser 10. Pushen naar Vercel Volledig stap-voor-stap zit in **`Les13-Stap-voor-stap.md`** (in lesbestanden). --- ## BLOK 5 — LIVE DEMO ### Slide 11: LIVE DEMO — Polderfest-agent in actie **Wat ik laat zien:** 1. Open de **gedeployde versie** van `polderfest-with-agent` in de browser 2. Plak prompt 1: *"Plan een avond met indie en techno voor zaterdag."* → Studenten zien meerdere tool-calls (searchBands × 2, getStageSchedule) 3. Plak prompt 2: *"Wat speelt er op zondag en hoe is het weer?"* → Agent gebruikt nu ook `getWeather` (externe API) 4. Plak prompt 3: *"Welke band moet ik NIET missen op vrijdag?"* → Agent doet creatieve combinatie, geeft mening **Daarna kijken we in de code:** - `app/api/agent/route.ts` — de drie tools + `stopWhen` - `app/agent/page.tsx` — UI met tool-call-weergave - Vergelijking met `app/api/chat/route.ts` (Les 11): "kijk hoeveel meer kan met agents" --- ## BLOK 6 — Nu jullie ### Slide 12: Nu jullie **Doel:** bouw zelf een Polderfest-agent vanaf jouw Polderfest-app uit Les 12. **Materialen (in `lesbestanden/`):** - `polderfest-original.zip` — startpunt - `polderfest-with-agent.zip` — referentie als je vastloopt - `Les13-Stap-voor-stap.md` — 11 stappen, volg ze één voor één **Stappen:** 1. Unzip de starter OF gebruik je eigen Polderfest-app uit Les 12 2. Volg `Les13-Stap-voor-stap.md` — werk in jouw eigen tempo 3. Test in de browser met de drie voorbeeld-prompts 4. Deploy naar Vercel (env vars niet vergeten!) 5. Deel je productie-URL in de chat **Vragen?** Type "vraag" in de chat of steek je hand op — ik loop rond. --- ## BLOK 7 — Afsluiting ### Slide 13: Wat we vandaag hebben gedaan - Verschil tool calling vs agent — `stopWhen` is de knop - Drie nieuwe AI SDK functies: `tool()`, `stepCountIs()`, multi-step loops - Externe APIs als tool — Open-Meteo, geen key - Polderfest-app uitgebreid: van chat-met-context naar echte agent - Live demo + zelf gebouwd **Volgende les (Les 14):** Externe APIs + Cursor + Vercel deploy in diepte. Vragen?