# Les 15 — Agents ## Slide Overzicht (Klas A — 3 uur fysiek, demo-driven) **Lesvorm:** Tim demonstreert klassikaal. Studenten kijken. Zelf bouwen = huiswerk. **Demo-app:** Nieuwe research-agent (from scratch, los van Polderfest) **Vervolg op:** Les 14 — RAG + Embeddings **Aansluit op:** Les 16 — MCP servers --- ## Slide 1: Title ### Les 15 — Agents **Visual:** - Background: CREAM - "Les 15" in BLUE - "Agents" in BLACK - Subtitle: "Een LLM in een loop met tools — autonoom tot het klaar is" --- ## Slide 2: Terugblik ### Waar staan we? **Vorige les (Les 12):** - Tool Calling — AI roept zelf functies aan - `tool({ description, inputSchema, execute })` - `stopWhen: stepCountIs(5)` — multi-step - Polderfest chat met 6 tools (search, stats, schedule, favorites) **Wat een tool-call bot nog NIET kan:** - Lange ketens (30+ stappen) - Eigen plan opstellen + bijstellen - Tools die andere tools triggeren - Dynamisch het model wisselen per stap **Vandaag: agents. Eén stap verder.** **Visual:** Pijltje van "5-step tool calling" naar "20-50 step agent loop" --- ## Slide 3: Planning ### Vandaag — 180 minuten | Onderwerp | Duur | |-----------|------| | Welkom + Terugblik | 10 min | | Theorie: wat is een agent? | 30 min | | **Live Demo 1** — Setup nieuwe research-agent | 25 min | | **Live Demo 2** — ToolLoopAgent + stopWhen | 25 min | | **Pauze** | 15 min | | **Live Demo 3** — prepareStep + dynamic control | 25 min | | **Live Demo 4** — Planning patterns + done-tool | 20 min | | Wanneer agent vs tool-call vs workflow? | 10 min | | Lesopdracht + Huiswerk uitleg | 15 min | | Vragen + Afsluiting | 5 min | **Format:** Demo-driven. Code-fragmenten in slides + live in editor. --- ## Slide 4: Wat is een agent? ### LLM + Tools + Loop **De definitie van Vercel AI SDK:** > Agents are LLMs that use tools in a loop to accomplish tasks. **Drie componenten:** 1. **LLM** — beslist wat de volgende actie is 2. **Tools** — uitbreiding (search, read, write, anything) 3. **Loop** — runtime die deze twee orchestreert - *Context management:* wat ziet model in elke stap - *Stopping condition:* wanneer is de taak klaar **Het verschil met Les 12:** - Les 12: tot 5 stappen, korte taken - Les 15: 20-50+ stappen, langere autonome workflows **Visual:** Loop-diagram — LLM → kies tool → execute → resultaat → LLM → ... → klaar --- ## Slide 5: De anatomie van de loop ### Wat gebeurt er per stap? ``` ┌─────────────────────────────────────┐ │ Loop iteratie (1 step): │ │ │ │ 1. Stuur messages naar model │ │ 2. Model genereert response: │ │ - text? → loop stopt │ │ - tool-call? → ga door │ │ 3. Voer tool execute() uit │ │ 4. Voeg tool-result toe aan msgs │ │ 5. Check stop-conditie │ │ 6. Volgende iteratie │ └─────────────────────────────────────┘ ``` **De loop stopt wanneer:** - Model geeft text in plaats van tool-call (natural finish), OF - `stopWhen`-conditie is voldaan, OF - Tool zonder execute wordt aangeroepen (done-pattern), OF - Tool-call needs approval **Default in v6:** `stepCountIs(20)` — veiligheidsgrens. --- ## Slide 6: ToolLoopAgent ### De nieuwe agent-abstractie in v6 **In plaats van zelf streamText loopen, gebruik je ToolLoopAgent:** ```typescript import { ToolLoopAgent, tool, stepCountIs } from "ai"; const researchAgent = new ToolLoopAgent({ model: "openai/gpt-4o", system: "You are a research assistant...", tools: { webSearch, readPage, saveReport, }, stopWhen: stepCountIs(30), }); const result = await researchAgent.generate({ prompt: "Onderzoek de impact van AI op de Nederlandse bouwsector", }); console.log(result.text); // antwoord console.log(result.steps); // alle stappen ``` **Wat krijg je:** - Minder boilerplate (geen eigen loop schrijven) - Herbruikbaar (definieer 1x, gebruik overal) - Built-in loop, context, stopping **Visual:** Side-by-side: handmatige while-loop vs ToolLoopAgent. --- ## Slide 7: Stop-condities ### Wanneer is een agent klaar? **Built-in condities:** | Conditie | Wanneer | Wanneer gebruiken | |----------|---------|-------------------| | `stepCountIs(N)` | Na N stappen | Default veiligheid | | `hasToolCall("done")` | Specifieke tool gebruikt | Done-pattern | | `isLoopFinished()` | Nooit — model bepaalt | Lange autonomie | **Combineren met array:** ```typescript stopWhen: [ stepCountIs(50), // max budget hasToolCall("submit"), // OF submit-tool aangeroepen ] ``` **Custom conditie:** ```typescript const budgetExceeded: StopCondition = ({ steps }) => { const cost = computeCost(steps); return cost > 0.50; // stop bij $0.50 }; ``` **Visual:** Drie traffic lights — rood (step limit), oranje (tool reached), groen (kostgrens). --- ## Slide 8: prepareStep ### Per stap iets anders doen **`prepareStep` runt VOOR elke stap. Je kunt aanpassen:** - Model wisselen (mini → sonnet voor complex) - Tools beperken (alleen search in fase 1, alleen write in fase 3) - Messages trimmen (context-budget bewaken) - `toolChoice` forceren **Voorbeeld — dynamic model:** ```typescript new ToolLoopAgent({ model: "openai/gpt-4o-mini", // default prepareStep: async ({ stepNumber, messages }) => { if (stepNumber > 2 && messages.length > 10) { return { model: "anthropic/claude-sonnet-4.5" }; } return {}; // niks aanpassen }, }); ``` **Voorbeeld — fase-gebaseerde tools:** ```typescript prepareStep: async ({ stepNumber }) => { if (stepNumber <= 3) return { activeTools: ["webSearch"] }; if (stepNumber <= 6) return { activeTools: ["readPage"] }; return { activeTools: ["saveReport"], toolChoice: "required" }; }; ``` --- ## Slide 9: Wat we vandaag bouwen ### Research-agent from scratch **Doel:** Een agent die zelfstandig een onderzoeksvraag beantwoordt door web te zoeken, pagina's te lezen, en een rapport in Supabase op te slaan. **Stack:** - Next.js 16 + TypeScript + Tailwind + Shadcn - AI SDK v6 (ToolLoopAgent) - Tavily API (web search) - Supabase (rapport opslag) - OpenAI gpt-4o / Anthropic Sonnet **Tools die we bouwen:** | Tool | Wat | Gebruik in flow | |------|-----|-----------------| | `webSearch` | Tavily query → 5 resultaten | Fase 1: oriëntatie | | `readPage` | URL → fulltext extractie | Fase 2: diepgang | | `saveReport` | Insert in `research_reports` | Fase 3: opslaan | | `done` | No-execute, signaal klaar | Eind: stoppen | **Visual:** Diagram van research-flow: vraag → search → read → save → done. --- ## Slide 10: LIVE DEMO 1 — Setup research-agent ### ~25 min **Wat ik laat zien:** 1. `pnpm create next-app research-agent --typescript --tailwind --app` 2. `pnpm add ai @ai-sdk/openai @ai-sdk/anthropic zod @supabase/supabase-js` 3. `.env.local` — TAVILY_API_KEY, OPENAI_API_KEY, SUPABASE_* 4. Supabase schema: `research_reports` (id, query, summary, sources jsonb, created_at) 5. `lib/tools.ts` — eerste tool `webSearch` met Tavily fetch 6. `lib/agent.ts` — `ToolLoopAgent` initialiseren 7. `app/api/research/route.ts` — POST endpoint die agent.generate() doet 8. Eerste test in terminal: `curl /api/research -d '{"query": "..."}'` **Belangrijk:** Tavily API key is gratis tier (1000 calls/maand). Studenten krijgen instructie om zelf account te maken. **Visual:** Folder-tree van de research-agent repo. --- ## Slide 11: LIVE DEMO 2 — ToolLoopAgent + stopWhen ### ~25 min **Wat ik laat zien:** 1. Tweede en derde tool toevoegen: `readPage`, `saveReport` 2. `ToolLoopAgent` configuren met alle drie + `stopWhen: stepCountIs(30)` 3. System prompt schrijven: "plan eerst, search dan, lees relevante pagina's, vat samen, sla op" 4. Test met `"Schrijf een rapport over de Polderfest 2027 lineup"` 5. `result.steps` loggen — zien dat agent 8-15 stappen doet 6. Wisselen naar `isLoopFinished()` — zien dat agent zelf stopt 7. `hasToolCall("saveReport")` toevoegen — stoppen zodra opgeslagen **Visual:** Console-log met alle stappen (toolName, input, output) — laat zien hoe agent zelf plant. --- ## Slide 12: Pauze ### 15 minuten --- ## Slide 13: LIVE DEMO 3 — prepareStep ### ~25 min **Wat ik laat zien:** **Use case 1 — Dynamic model:** - Default: `gpt-4o-mini` (snel + goedkoop) - Vanaf stap 5: `claude-sonnet-4.5` (beter reasoning) - Console-log per stap welk model **Use case 2 — Fase-gebaseerde tools:** - Stap 0-3: alleen `webSearch` (oriëntatie) - Stap 4-7: alleen `readPage` (diepgang) - Stap 8+: alleen `saveReport` + `done` (afronden) - Zien: agent kan niet 'cheaten' door te vroeg op te slaan **Use case 3 — Context-trimming:** - Na 15 messages: trim oude tool-results - System prompt + laatste 10 berichten - Voorkomt token-explosie bij lange agents **Visual:** Timeline-strip met de drie fasen + model-switch. --- ## Slide 14: LIVE DEMO 4 — Done-tool + custom stop ### ~20 min **Wat ik laat zien:** **Pattern 1 — Done-tool (no-execute):** ```typescript done: tool({ description: "Signaleer dat onderzoek klaar is.", inputSchema: z.object({ finalReportId: z.number(), summary: z.string(), }), // GEEN execute — stopt de loop }) ``` Met `toolChoice: "required"` forceer je dat agent ALTIJD een tool aanroept — en `done` is hoe-ie stopt. **Pattern 2 — Custom stop op kosten:** ```typescript const costLimit: StopCondition = ({ steps }) => { const tokens = steps.reduce((sum, s) => sum + (s.usage?.totalTokens ?? 0), 0); return tokens > 50_000; }; ``` **Pattern 3 — Plan-act-reflect loop:** - Stap 0: agent maakt plan (text) - Stap 1-N: voert plan uit (tools) - Eind: agent schrijft reflectie (text) **Visual:** Plan-Act-Reflect ReAct-diagram. --- ## Slide 15: Wanneer agent vs tool-call vs workflow? ### Niet alles hoeft autonoom | Scenario | Aanpak | |----------|--------| | Vraag → 1 tool → antwoord | Plain tool-call | | Vraag → 2-5 tools → antwoord | `stopWhen: stepCountIs(5)` (Les 12) | | Onderzoek → 10-50 tools → rapport | **Agent** (Les 15) | | Productie pipeline met validatie | **Workflow** (explicit code) | | Wettelijk: must be reproducible | **Workflow** — geen agent | **Wanneer GEEN agent gebruiken:** - Deterministisch nodig (audit, finance, juridisch) - Voorspelbare kosten - Latency-sensitive (< 1s antwoord) **Wanneer WEL agent:** - Open-ended taken (research, planning, debugging) - Tot stand komen via meerdere stappen - Cost en latency mag wat hoger **Quote uit AI SDK docs:** *"Agents are flexible and powerful, but non-deterministic. When you need reliable, repeatable outcomes, use workflow patterns."* --- ## Slide 16: Lesopdracht + Huiswerk ### Bouw je eigen agent **Lesopdracht (in-class, 30 min):** - Setup research-agent in eigen repo - Tavily account aanmaken + key in .env - Agent draaien met `stepCountIs(10)` en eerste eigen query stellen - Logs bekijken: hoeveel stappen, welke tools **Huiswerk (voor Les 14):** - 4e tool toevoegen — `listReports` om opgeslagen rapporten op te halen - `prepareStep` toevoegen — minimaal 1 use case (model OF tools OF context) - Custom `StopCondition` schrijven (kosten OF specifieke conditie) - `AGENT.md` schrijven: tool-lijst + stop-strategie + 1 voorbeeld-run met logs **Bonus:** - UI met live-step-rendering (elke stap als card) - Sub-agent: 2e agent die per pagina samenvat, hoofdagent gebruikt sub-agent als tool --- ## Slide 17: Volgende les + Afsluiting ### Vragen? **Vandaag gezien:** - Agent = LLM + tools + loop - `ToolLoopAgent` met `stopWhen` en `prepareStep` - 4 stop-condities: stepCountIs, hasToolCall, isLoopFinished, custom - prepareStep voor dynamic model / tools / context - Done-tool pattern voor forced tool calling - Wanneer wel/niet een agent **Volgende les (Les 16): MCP — Model Context Protocol** - Semantic search op grote datasets - pgvector in Supabase - Embedding models — wat zijn vectors - RAG-pipeline: chunk → embed → retrieve → generate - Combo: RAG-tool in een agent — best of both worlds **Daarna in deze leerlijn:** - Les 15-16: Testing + Deployment + Performance - Les 17-18: Eindopdracht-werkdagen + Pitch **Vragen? Feedback?** --- ## Slide Summary | # | Title | Type | |---|-------|------| | 1 | Title | Opening | | 2 | Terugblik | Recap | | 3 | Planning | 180-min | | 4 | Wat is een agent | Theorie | | 5 | Anatomie van de loop | Theorie | | 6 | ToolLoopAgent | Theorie | | 7 | Stop-condities | Theorie | | 8 | prepareStep | Theorie | | 9 | Wat we vandaag bouwen | Intro demo | | 10 | **LIVE DEMO 1** — Setup | Demo | | 11 | **LIVE DEMO 2** — stopWhen | Demo | | 12 | Pauze | Break | | 13 | **LIVE DEMO 3** — prepareStep | Demo | | 14 | **LIVE DEMO 4** — done + custom stop | Demo | | 15 | Wanneer wel/niet | Reflectie | | 16 | Lesopdracht + Huiswerk | Praktijk | | 17 | Afsluiting + Les 14 preview | Closing | --- ## Bronnen - AI SDK Agents — Overview: https://ai-sdk.dev/docs/agents/overview - AI SDK Agents — Loop Control: https://ai-sdk.dev/docs/agents/loop-control - AI SDK Agents — Building Agents: https://ai-sdk.dev/docs/agents/building-agents - AI SDK Agents — Workflows: https://ai-sdk.dev/docs/agents/workflows - Tavily API: https://tavily.com/ - Anthropic — Building effective agents: https://www.anthropic.com/research/building-effective-agents