# Les 12 — Lesopdracht
## Refactor jouw thema-app naar Tool Calling

**Vak:** AI-Assisted Development
**Opleiding:** NOVI Hogeschool Utrecht
**Wanneer:** Thuis, vóór volgende les
**Inleveren:** GitHub URL + screenshots van werkende multi-step chat

---

## Doel

Bouw voort op je **eigen thema-app** uit Les 11. Refactor de chat-route — weg met de hele dataset meesturen. Vervang door **tools** die AI zelf kan aanroepen.

Je oefent:
- Tools definiëren met description + inputSchema + execute
- `stopWhen: stepCountIs(N)` voor multi-step queries
- System prompts voor tool-gebruik aansturen
- Multi-step vragen testen

---

## Vereisten

- Werkende app uit Les 11 (Next.js + Supabase + chat met data)
- Eigen thema (geen Polderfest namaken)
- 100+ records in je Supabase
- OpenAI key in `.env.local`

> Heb je geen werkende Les 11 app? Eerst die afmaken. Deze opdracht bouwt erop voort.

---

## Wat moet er staan?

### Code

- [ ] **Chat-route gerefactord** — geen `.select("*")` aan begin van POST meer
- [ ] **Minstens 3 tools** gedefinieerd voor jouw dataset
- [ ] Eén tool met **enum parameters** (vaste keuze)
- [ ] Eén tool met **optional filters** (`.optional()` parameters)
- [ ] `stopWhen: stepCountIs(5)` in `streamText`
- [ ] System prompt aangepast: "gebruik tools, verzin niet"

### Werking

- [ ] Chat werkt nog (geen 500-errors)
- [ ] Minstens 3 vragen die elk **1 tool** triggeren
- [ ] Minstens 1 vraag die **2+ tools** triggert (multi-step)
- [ ] AI verzint niet meer — tool-results worden gebruikt

---

## Tools voor jouw thema — voorbeelden

### Restaurant-aggregator

| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchRestaurants` | cuisine?, price_range?, neighborhood? | Filter restaurants |
| `getRestaurantById` | id | Detail + menu |
| `getCuisineStats` | (geen) | Verdeling per cuisine |

### Scriptie-archief

| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchTheses` | year?, supervisor?, keyword? | Filter scripties |
| `getThesisAbstract` | id | Volledige samenvatting |
| `getYearStats` | (geen) | Telling per jaar |

### Museum-collectie

| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchArtworks` | artist?, period?, medium? | Filter kunstwerken |
| `getArtworkDetails` | id | Detail + provenance |
| `getPeriodStats` | (geen) | Verdeling per stroming |

**Voor jouw thema — bedenk:**
- Wat filtert iemand vaak? → `searchX` met filter-parameters
- Wat is een unieke entiteit? → `getXById` of `getXByName`
- Welke aggregaties zijn interessant? → `getStats`

---

## Stappenplan

### Stap 1 — Backup huidige chat-route (2 min)

```bash
cp app/api/chat/route.ts app/api/chat/route.les11.ts.bak
```

Voor het geval de refactor faalt.

### Stap 2 — Refactor route.ts (20 min)

Open `app/api/chat/route.ts`. Verwijder:
- `const { data: bands } = await supabase...select("*")` aan begin
- De grote `context` string
- De grote system prompt met alle data

Voeg toe:
- `import { tool } from "ai"` en `import { z } from "zod"`
- Tool-definities boven je POST-functie
- `tools: { ... }` en `stopWhen: stepCountIs(5)` in `streamText` (importeer `stepCountIs` uit `"ai"`)
- Kortere system prompt — alleen rol + tool-tips

### Stap 3 — Eerste tool: searchX (15 min)

Hier het patroon — pas aan voor jouw thema:

```typescript
const searchItems = tool({
  description:
    "Zoek items in [thema-naam]. Filter op X, Y, of Z. " +
    "Gebruik dit voor filtervragen.",
  inputSchema: z.object({
    category: z.enum(["A", "B", "C"]).optional(),
    minRating: z.number().min(1).max(5).optional(),
    keyword: z.string().optional().describe("Zoekterm in titel of beschrijving"),
  }),
  execute: async ({ category, minRating, keyword }) => {
    let q = supabase.from("items").select("*");
    if (category) q = q.eq("category", category);
    if (minRating) q = q.gte("rating", minRating);
    if (keyword) q = q.ilike("title", `%${keyword}%`);
    const { data, error } = await q.limit(20);
    if (error) return { error: error.message };
    return { count: data.length, items: data };
  },
});
```

### Stap 4 — Twee extra tools (15 min)

Voeg minstens 2 meer toe. Inspiratie boven.

### Stap 5 — System prompt aanpassen (5 min)

```typescript
const system = `Je bent een assistent voor [thema-naam].
Gebruik de beschikbare tools om vragen te beantwoorden.

Tips:
- Voor "welke X met Y?" → searchItems
- Voor "vertel me over X" → getItemById
- Voor "hoeveel" of "verdeling" → getStats

Verzin nooit data. Antwoord in het Nederlands.`;
```

### Stap 6 — Test multi-step (15 min)

In je chat, probeer:

1. **Single tool** (`searchItems` triggert):
   ```
   Welke [items] hebben [filter]?
   ```

2. **Single tool** (`getItemById` triggert):
   ```
   Vertel me alles over [specifieke item].
   ```

3. **Single tool** (`getStats` triggert):
   ```
   Hoeveel [items] in totaal? En per [groep]?
   ```

4. **Multi-step** (2+ tools):
   ```
   Geef me 3 [items] in categorie X, en vergelijk ze qua [eigenschap].
   ```

### Stap 7 — Screenshots maken (8 min)

Voor je inleveren bij Brightspace:
- 1 screenshot per single-tool vraag (3 stuks)
- 1 screenshot van multi-step vraag (waar je 2 tool-calls ziet — als je UI ze toont)

---

## Inleveren

1. **GitHub URL** in Brightspace
2. **4 screenshots** in je README (3× single + 1× multi-step)
3. **Eén alinea** in README: welke tools heb je gedefinieerd? Waarom deze?

---

## Veelvoorkomende problemen

| Probleem | Oplossing |
|----------|-----------|
| AI roept geen tools aan | Description verbeteren — wees specifieker |
| AI gebruikt 1 tool meerdere keren | System prompt — zeg "kies juiste tool" |
| AI returnt foutmelding "Tool args invalid" | Zod schema te strict — gebruik `.optional()` waar nodig |
| `Cannot find module 'zod'` | `npm install zod` |
| Tool execute crasht | Error throwen → niet doen, return `{ error: "..." }` |
| Multi-step werkt niet | `stopWhen: stepCountIs(5)` toegevoegd? Default is 1 stap. |

---

## Tijd-indicatie

| Stap | Tijd |
|------|------|
| Backup + refactor route | 22 min |
| 3 tools definiëren | 30 min |
| System prompt + multi-step | 20 min |
| Testen + screenshots | 23 min |
| **Totaal** | **~1,5 uur** |

Loop je vast? Vraag op Brightspace.

---

## Tips

- **Begin klein** — eerst één tool werkend. Dan twee. Dan drie. Niet alles tegelijk.
- **Schrijf descriptions zoals voor een collega** — "Doe X als gebruiker vraagt om Y."
- **Test direct na elke tool** — werkt 't? Goed. Werkt 't niet? Beschrijving aanpassen.
- **Gebruik enums** voor vaste keuzes — AI respecteert ze automatisch.

Succes! Volgende les zien we hoe ver dit kan met Agents.
