fix: vercel

This commit is contained in:
2026-06-09 18:02:04 +02:00
parent ee69da1665
commit c023192113
85 changed files with 10266 additions and 3008 deletions

View File

@@ -0,0 +1,304 @@
# Les 13 — Agents (Klas A)
> **Deel 3: AI Development** (Les 1116)
> **Lesvorm:** fysiek, demo-driven
> **Structuur:** ±1 uur presenteren → pauze → ±1,5 uur zelf bouwen
---
## Blok-structuur
| Blok | Onderwerp | Slides |
|------|-----------|--------|
| 1 | Welkom + Terugblik tool calling | 13 |
| 2 | Wat is een agent? | 46 |
| 3 | AI SDK basics: tool, stopWhen, externe API | 79 |
| 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 13 (ook met `stopWhen`) | Vaak 410+, 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?