fix: vercel
This commit is contained in:
304
Les13-Agents/Les13-Slide-Overzicht.md
Normal file
304
Les13-Agents/Les13-Slide-Overzicht.md
Normal file
@@ -0,0 +1,304 @@
|
||||
# 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?
|
||||
Reference in New Issue
Block a user