12 KiB
Les 12 — Tool Calling
Slide Overzicht (Klas A — 3 uur fysiek, demo-driven)
Lesvorm: Tim demonstreert klassikaal. Studenten kijken. Zelf bouwen = thuis. Demo-app: Polderfest 2027 (verder bouwen op Les 11) Vervolg op: Les 11 — Vercel AI SDK + chat met data Aansluit op: Les 13 — Agents + autonome multi-step workflows
Slide 1: Title
Les 12 — Tool Calling
Visual:
- Background: CREAM
- "Les 12" in BLUE
- "Tool Calling" in BLACK
- Subtitle: "Laat AI zelf kiezen welke functie aan te roepen"
Slide 2: Terugblik
Waar staan we?
Vorige les:
- Vercel AI SDK basics + 4 kern-functies
- Polderfest 2027 demo — 500 bands in Supabase
- Chat-route met
streamText+useChat - AI antwoordt op vragen over de data
Het probleem dat we toen lieten zien:
- Vandaag sturen we ALLE 500 bands mee als context bij elke vraag
- ~30.000 tokens per call — werkt voor 500, niet voor 50.000
Vandaag lossen we dat op met Tool Calling.
Visual: Pijltje van "alles meesturen" naar "AI kiest tools"
Slide 3: Planning
Vandaag — 180 minuten
| Onderwerp | Duur |
|---|---|
| Welkom + Terugblik + schaalprobleem recap | 10 min |
| Theorie: wat is Tool Calling? | 30 min |
| Live Demo 1 — Eerste tool: searchBands | 20 min |
| Live Demo 2 — Multi-step + meer tools | 20 min |
| Pauze | 15 min |
| Live Demo 3 — Tool-calls in UI tonen | 25 min |
| Live Demo 4 — Edge cases + error handling | 15 min |
| Waarom Tool Calling > context-all? | 5 min |
| Lesopdracht + Huiswerk uitleg | 20 min |
| Vragen + Afsluiting | 15 min |
Format: Demo-driven, jullie kijken mee.
Slide 4: Wat is Tool Calling?
AI besluit zelf welke functie te gebruiken
Het idee: In plaats van alle data mee te sturen, geef je AI tools (functies). AI ziet een vraag, kiest welke tool relevant is, roept 'm aan met de juiste parameters, krijgt resultaat, antwoordt.
Voorbeeld-flow:
User: "Welke bands spelen vrijdag op de Main Stage?"
↓
AI: ik roep searchBands({ day: "Vrijdag", stage: "Main Stage" }) aan
↓
Supabase: 12 bands
↓
AI: "Op vrijdag op de Main Stage spelen: ..."
Wat krijg je:
- Schaalbaar (10 records of 10 miljoen — werkt hetzelfde)
- Real-time data (geen verouderde context)
- Type-safe (Zod schema voor parameters)
- Multi-step (AI kan meerdere tools combineren)
Visual: Schema diagram chat → tool → DB → AI → antwoord.
Slide 5: Anatomie van een Tool
description + inputSchema + execute
import { tool } from "ai";
import { z } from "zod";
const searchBands = tool({
description: "Zoek bands op dag, stage, of genre",
inputSchema: z.object({
day: z.enum(["Vrijdag", "Zaterdag", "Zondag"]).optional(),
stage: z.string().optional(),
genre: z.string().optional(),
}),
execute: async ({ day, stage, genre }) => {
// Supabase query
const { data } = await supabase.from("bands").select("*")
.eq("day", day || undefined)
.eq("stage", stage || undefined);
return data;
},
});
Drie verplichte delen:
description— Wat doet de tool? AI leest dit om te beslissen.inputSchema— Wat heeft de tool nodig? Zod schema = type-safe.execute— Wat gebeurt er als de tool wordt aangeroepen?
Belangrijk: beschrijvingen zijn kritiek. AI kiest op basis van descriptions — vaag = verkeerde keuze.
Slide 6: Multi-step met stopWhen
Eén vraag = meerdere tool-calls
Het concept:
Met stopWhen: stepCountIs(5) geef je AI toestemming om tot 5 keer een tool aan te roepen voordat hij antwoordt.
Voorbeeld:
User: "Vergelijk de top headliner met de drukst geplande opener"
↓
AI: stap 1 — searchBands({ tier: "headliner" }) → 50 bands
↓
AI: stap 2 — searchBands({ tier: "opener" }) → 100 bands
↓
AI: stap 3 — verwerkt + vergelijkt
↓
AI: antwoordt met vergelijking
In code:
const result = streamText({
model: openai("gpt-4o-mini"),
tools: { searchBands, getStats, getBandByName },
stopWhen: stepCountIs(5),
messages,
});
Visual: Flowchart met meerdere tool-blokjes.
Slide 7: Vandaag — refactor Polderfest naar Tool Calling
Wat gaan we bouwen?
Stap voor stap:
- Refactor de chat-route van Les 11 — weg met alle bands meesturen
- Eerste tool:
searchBandsmet filter-parameters - Tweede en derde tool:
getStats,getBandByName,getScheduleByDay - Multi-step in actie — vragen die 2-3 tools combineren
- UI uitbreiden — tonen welke tools AI aanriep (transparantie)
- Edge cases: ongeldige input, lege resultaten, errors
Tools die we vandaag bouwen (6 stuks):
| Tool | Wat | Tier |
|---|---|---|
searchBands |
Filter op dag, stage, genre, tier | Read |
getBandByName |
Exact lookup | Read |
getStats |
Aggregate (count per groep) | Read |
getScheduleByDay |
Slot-overzicht per dag | Read |
addFavorite |
User favorite toevoegen | Write |
listFavorites |
User favorieten ophalen | Read |
Visual: Tools-lijst met read/write icons.
Slide 8: LIVE DEMO 1 — Eerste tool: searchBands
~20 min
Wat ik laat zien:
- Refactor
app/api/chat/route.tsvan Les 11 — weg met de hele context-string - Import
toolvanai - Eerste tool definiëren:
searchBandsmet description + inputSchema + execute - System prompt aanpassen: "Gebruik tools, verzin niet"
tools: { searchBands }+stopWhen: stepCountIs(5)toevoegen aanstreamText- Browse naar
/chat, vraag: "Welke bands spelen zaterdag op de Beach Stage?" - Zien: AI roept tool aan met juiste params → antwoordt
Visual: Side-by-side mock-up: oude chat-route vs nieuwe met tools.
Slide 9: LIVE DEMO 2 — Meer tools + multi-step
~20 min
Wat ik laat zien:
- Tweede tool:
getStats— voor "hoeveel jazz acts?" - Derde tool:
getBandByName— voor "vertel me over Lost Tigers" - Vierde tool:
getScheduleByDay— voor "tijdschema vrijdag Main Stage" - System prompt verfijnen — wanneer welke tool
- Vraag stellen die meerdere tools triggert: "Vergelijk twee genres qua headliners"
- Tonen:
stopWhenin actie — 2-3 tool-calls in één antwoord
Visual: Multi-step flow diagram.
Slide 10: Pauze
15 minuten
Slide 11: LIVE DEMO 3 — Tool-calls in UI tonen
~25 min
Wat ik laat zien:
useChatreturntmessagesmet parts — text én tool-invocations- UI uitbreiden: parts loopen i.p.v. content
- Tool-call rendering: "🔧 searchBands({ day: 'Vrijdag', stage: 'Main' })"
- Tool-result rendering: collapsed by default, klik om uit te klappen
- Streaming tool-calls visualiseren — typing-effect ook bij tool-naam
- Bonus: loading-icoon tijdens tool-execute
Waarom transparantie?
- Studenten zien wat AI doet (debug-hulp)
- Vertrouwen — gebruiker ziet "ja, hij heeft echt de DB geraadpleegd"
- Voor productie: optioneel kunt verstoppen, voor demo onmisbaar
Visual: Mock-up van chat met tool-call chips.
Slide 12: LIVE DEMO 4 — Edge cases + error handling
~15 min
Wat ik laat zien:
Edge case 1: ongeldige input
- Vraag: "Welke bands op Donderdag?"
- AI ziet:
dayparameter is enum — Donderdag bestaat niet - Twee opties: AI weigert, of probeert ander filter
Edge case 2: lege resultaat
- Vraag: "Death metal bands?"
- Tool returnt lege array
- AI legt uit: "Geen death metal acts op Polderfest 2027"
Edge case 3: database error
- Wat als Supabase down is? Tool returnt
{ error: "..." } - AI moet dit netjes communiceren — niet hallucineren
Edge case 4: write tool — addFavorite
- Demo: AI voegt favoriet toe
- Confirmation tonen — "✓ toegevoegd aan favorieten"
- Belangrijk: AI mag write-tools niet zonder expliciete user-intent gebruiken
Visual: 4 edge-case scenarios + fixes.
Slide 13: Waarom Tool Calling > context-all?
De vergelijking
| Aspect | Les 11 (context-all) | Les 12 (tool calling) |
|---|---|---|
| Tokens per call | ~30.000 (500 bands) | ~2.000 (tools + result) |
| Schaal | Tot ~1000 records | Tot duizenden |
| Live data | Snapshot bij start | Actueel per call |
| Write operaties | Niet mogelijk | Wel (addFavorite) |
| Multi-step | Beperkt | Native (stopWhen) |
| Cost | Hoger | Lager |
| Complexiteit | Lager | Iets hoger |
Wanneer toch context-all?
- Heel kleine dataset (<100 records)
- Snel prototype
- Geen schaal nodig
Voor productie: bijna altijd Tool Calling.
Slide 14: Lesopdracht
Bouw tools voor jouw eigen thema-app
Voor thuis — bouw voort op je app uit Les 11:
- Refactor je chat-route — weg met de hele context-string
- Definieer minstens 3 tools voor je eigen dataset
- Voeg
stopWhen: stepCountIs(5)toe aan jestreamText - Pas system prompt aan: "gebruik tools, verzin niet"
- Test 3 vragen die meerdere tools combineren
Tools voorbeelden (afhankelijk van jouw thema):
searchX(filter)— read met filtersgetXById(id)— exact lookupgetStats(groupBy)— aggregate- Voor jouw thema-specifieke acties
Eisen:
- Werkende refactor (chat werkt nog)
- Min 3 tools waarvan minstens 1 met enum parameters
- Min 1 vraag die 2+ tools combineert (multi-step)
Slide 15: Huiswerk
Tools uitbreiden + UI visualisatie + write-tool
Voor volgende week (Les 13):
Onderdeel A — Write-tool toevoegen
- Maak een
user_Xtabel in Supabase (favorites, notes, votes, ...) - Schrijf write-tool:
addX(userId, itemId) - Stel een vraag die deze tool triggert: "voeg X toe aan mijn lijst"
Onderdeel B — Tool-calls in UI
- Refactor je chat UI om tool-invocations te tonen
- Style: chip / badge / collapsed result
- Reden: transparantie + debug
Onderdeel C — TOOLS.md
Schrijf in repo-root:
- Welke tools heb je gedefinieerd? (lijst + descriptions)
- 3 vragen die 1 tool gebruiken
- 1 vraag die 2+ tools combineert (multi-step)
- 1 voorbeeld van een edge-case die AI goed afhandelde
Bonus: Loading indicator per tool-execute, tool-result formatten als kaartjes.
Slide 16: Volgende les — Agents + autonomie
Hoe ver kan een AI autonoom?
Wat we vandaag deden:
- AI roept tools aan in 1 ronde, maximaal 5 stappen
- Antwoord komt terug naar gebruiker
Volgende les (Les 13):
- AI Agents — langere autonome workflows
stopWhen: stepCountIs(20)of meer — AI plant, voert uit, evalueert, herhaalt- Tools die andere tools triggeren
- Stop-condities, retries, error recovery
- Voorbeeld: "Plan mijn volledige Polderfest weekend" — AI bekijkt alle dagen, maakt schema, voegt toe aan favorieten
Daarna in deze leerlijn:
- Les 14: RAG + embeddings (semantic search op grote datasets)
- Les 15-16: Testing + Deployment + Performance
- Les 17-18: Eindopdracht-werkdagen + Pitch
Slide 17: Afsluiting
Vragen?
Vandaag gezien:
- Schaalprobleem van context-all opgelost met Tool Calling
- Anatomie van een tool: description + inputSchema + execute
stopWhenvoor multi-step workflows- Zes tools voor Polderfest gebouwd
- Tool-invocations in UI gevisualiseerd
- Edge cases + error handling
Volgende les: Agents + autonomie
Vragen? Feedback?
Slide Summary
| # | Title | Type |
|---|---|---|
| 1 | Title | Opening |
| 2 | Terugblik + schaalprobleem | Recap |
| 3 | Planning | 180-min |
| 4 | Wat is Tool Calling | Theorie |
| 5 | Anatomie van een tool | Theorie |
| 6 | Multi-step met stopWhen | Theorie |
| 7 | Vandaag bouwen we | Intro demo |
| 8 | LIVE DEMO 1 — searchBands | Demo |
| 9 | LIVE DEMO 2 — Multi-step + meer tools | Demo |
| 10 | Pauze | Break |
| 11 | LIVE DEMO 3 — Tool-calls in UI | Demo |
| 12 | LIVE DEMO 4 — Edge cases | Demo |
| 13 | Tool Calling vs context-all | Reflectie |
| 14 | Lesopdracht | Praktijk |
| 15 | Huiswerk | Praktijk |
| 16 | Volgende les: Agents | Preview |
| 17 | Afsluiting | Closing |
Bronnen
- Vercel AI SDK Tools: https://ai-sdk.dev/docs/foundations/tools
- Multi-step: https://ai-sdk.dev/docs/foundations/agents
- Zod docs: https://zod.dev
- OpenAI Function Calling docs: https://platform.openai.com/docs/guides/function-calling
- Supabase JS query builder: https://supabase.com/docs/reference/javascript/select