fix: les 6
This commit is contained in:
@@ -1,483 +1,207 @@
|
||||
# Les 17: Vercel AI SDK, Tool Calling & Agents
|
||||
# Les 17: Eindproject Polish & Code Review
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer niet alleen chat interfaces bouwen, maar ook hoe AI externe data kan ophalen via Tool Calling en autonome taken kan uitvoeren als Agent.
|
||||
Finale polish fase van je eindproject. Focus op code review, peer feedback, en laatste verbeteringen voor inlevering. Voorbereiding op presentatie.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de Cursor .cursorrules ervaringen uit Les 16 - welke regels zorgen voor betere AI output?
|
||||
Bespreek klassikaal de werkdag voortgang uit Les 16 - wat hebben jullie afgekregen, wat bleek moeilijker dan verwacht?
|
||||
|
||||
### Waarom Vercel AI SDK?
|
||||
### Code Review Checklist
|
||||
|
||||
**Het probleem:** Direct API calls naar OpenAI/Anthropic zijn complex:
|
||||
- Streaming handmatig implementeren
|
||||
- Error handling
|
||||
- State management
|
||||
- Tool calling implementeren
|
||||
**TypeScript & Code Quality:**
|
||||
- [ ] No TypeScript errors
|
||||
- [ ] No `any` types
|
||||
- [ ] Props properly typed
|
||||
- [ ] Error handling complete
|
||||
- [ ] No console.logs in production
|
||||
|
||||
**De oplossing:** Vercel AI SDK
|
||||
- Simpele React hooks (`useChat`, `useCompletion`)
|
||||
- Built-in streaming
|
||||
- Provider-agnostic (OpenAI, Anthropic, etc.)
|
||||
- **Tool calling out-of-the-box**
|
||||
- **Agent capabilities met `maxSteps`**
|
||||
**React Best Practices:**
|
||||
- [ ] No unnecessary re-renders
|
||||
- [ ] Keys properly set in lists
|
||||
- [ ] Hooks rules followed
|
||||
- [ ] Components split logically
|
||||
- [ ] Prop drilling minimized
|
||||
|
||||
**Styling & UX:**
|
||||
- [ ] Responsive design working
|
||||
- [ ] Mobile friendly
|
||||
- [ ] Consistent styling
|
||||
- [ ] Accessible (alt text, labels, etc.)
|
||||
- [ ] No visual bugs
|
||||
|
||||
**Performance:**
|
||||
- [ ] Lighthouse > 80
|
||||
- [ ] Lazy load images
|
||||
- [ ] Optimize bundles
|
||||
- [ ] Fast interactions
|
||||
- [ ] Minimal flickering
|
||||
|
||||
---
|
||||
|
||||
### Installatie & Setup
|
||||
### Peer Review Process
|
||||
|
||||
```bash
|
||||
npm install ai @ai-sdk/openai zod
|
||||
# zod is nodig voor tool parameter validatie
|
||||
```
|
||||
**Hoe peer review doen:**
|
||||
|
||||
**Environment variable:**
|
||||
```bash
|
||||
# .env.local
|
||||
OPENAI_API_KEY=sk-xxxxx
|
||||
```
|
||||
1. **Voorbereiding (10 min)**
|
||||
- Share productie URL of GitHub link
|
||||
- List main features
|
||||
- Highlight AI features
|
||||
|
||||
2. **Review (15 min)**
|
||||
- Reviewer tests alle features
|
||||
- Takes notes
|
||||
- Looks at code (if applicable)
|
||||
|
||||
3. **Feedback (10 min)**
|
||||
- ✅ Wat werkt goed
|
||||
- ⚠️ What could improve
|
||||
- ❌ Any bugs found
|
||||
|
||||
4. **Discussion (5 min)**
|
||||
- Q&A
|
||||
- Discuss suggestions
|
||||
- Agree on priorities
|
||||
|
||||
---
|
||||
|
||||
### Deel 1: Basic Chat (Herhaling)
|
||||
### Final Checklist for Submission
|
||||
|
||||
#### useChat Hook
|
||||
**Functionality:**
|
||||
- [ ] All features work in production
|
||||
- [ ] Auth flows complete
|
||||
- [ ] CRUD operations complete
|
||||
- [ ] AI feature functional
|
||||
- [ ] No console errors
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
**Documentation:**
|
||||
- [ ] README.md complete
|
||||
- [ ] PROMPT-LOG.md has 10+ entries
|
||||
- [ ] AI-DECISIONS.md has 5+ entries
|
||||
- [ ] .env.example up to date
|
||||
- [ ] Setup instructions clear
|
||||
|
||||
export function ChatComponent() {
|
||||
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
|
||||
**Code Quality:**
|
||||
- [ ] Code is clean and organized
|
||||
- [ ] Comments where needed
|
||||
- [ ] Consistent naming
|
||||
- [ ] No dead code
|
||||
- [ ] .cursorrules present
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen">
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
{messages.map(m => (
|
||||
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
|
||||
<span className="inline-block p-2 rounded-lg bg-gray-100">
|
||||
{m.content}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
**Performance & UX:**
|
||||
- [ ] Lighthouse score > 80
|
||||
- [ ] Loading states visible
|
||||
- [ ] Error states handled
|
||||
- [ ] Mobile responsive
|
||||
- [ ] Fast load times
|
||||
|
||||
<form onSubmit={handleSubmit} className="p-4 border-t">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Type a message..."
|
||||
className="w-full p-2 border rounded"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Basic API Route
|
||||
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { streamText } from 'ai'
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: 'You are a helpful assistant.',
|
||||
messages,
|
||||
})
|
||||
|
||||
return result.toDataStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Deel 2: Tool Calling - AI + Externe Data
|
||||
|
||||
**Het probleem met basic chat:**
|
||||
- AI kent alleen zijn training data
|
||||
- Geen toegang tot realtime informatie
|
||||
- Kan geen acties uitvoeren
|
||||
|
||||
**De oplossing: Tool Calling**
|
||||
- Definieer "tools" die AI kan aanroepen
|
||||
- AI besluit zelf wanneer een tool nodig is
|
||||
- Tool haalt data op → AI interpreteert resultaat
|
||||
|
||||
#### Voorbeeld: Cocktail Advisor met TheCocktailDB
|
||||
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { streamText, tool } from 'ai'
|
||||
import { z } from 'zod'
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: `Je bent een cocktail expert.
|
||||
Gebruik de tools om cocktails te zoeken en recepten op te halen.
|
||||
Geef persoonlijk advies op basis van de resultaten.`,
|
||||
messages,
|
||||
tools: {
|
||||
// Tool 1: Zoek cocktails op ingrediënt
|
||||
searchByIngredient: tool({
|
||||
description: 'Zoek cocktails die een specifiek ingrediënt bevatten',
|
||||
parameters: z.object({
|
||||
ingredient: z.string().describe('Het ingrediënt om op te zoeken, bijv. "rum" of "vodka"')
|
||||
}),
|
||||
execute: async ({ ingredient }) => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${ingredient}`
|
||||
)
|
||||
const data = await res.json()
|
||||
return data.drinks?.slice(0, 5) || []
|
||||
}
|
||||
}),
|
||||
|
||||
// Tool 2: Haal cocktail details op
|
||||
getCocktailDetails: tool({
|
||||
description: 'Haal het volledige recept van een cocktail op',
|
||||
parameters: z.object({
|
||||
cocktailId: z.string().describe('Het ID van de cocktail')
|
||||
}),
|
||||
execute: async ({ cocktailId }) => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${cocktailId}`
|
||||
)
|
||||
const data = await res.json()
|
||||
return data.drinks?.[0] || null
|
||||
}
|
||||
}),
|
||||
|
||||
// Tool 3: Zoek non-alcoholische opties
|
||||
searchNonAlcoholic: tool({
|
||||
description: 'Zoek non-alcoholische cocktails/mocktails',
|
||||
parameters: z.object({}),
|
||||
execute: async () => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/filter.php?a=Non_Alcoholic`
|
||||
)
|
||||
const data = await res.json()
|
||||
return data.drinks?.slice(0, 5) || []
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return result.toDataStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
**Wat gebeurt er?**
|
||||
```
|
||||
User: "Ik heb rum en limoen, wat kan ik maken?"
|
||||
|
||||
AI denkt: "Ik moet zoeken op rum"
|
||||
→ Roept searchByIngredient({ ingredient: "rum" }) aan
|
||||
→ Krijgt: [{ name: "Mojito", id: "11000" }, { name: "Daiquiri", id: "11006" }, ...]
|
||||
|
||||
AI denkt: "Mojito klinkt goed met limoen, laat me het recept ophalen"
|
||||
→ Roept getCocktailDetails({ cocktailId: "11000" }) aan
|
||||
→ Krijgt: { name: "Mojito", ingredients: [...], instructions: "..." }
|
||||
|
||||
AI antwoordt: "Met rum en limoen kun je een heerlijke Mojito maken!
|
||||
Je hebt nog nodig: verse munt en suiker..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Deel 3: Agents - Autonome Multi-Step AI
|
||||
|
||||
**Van Tool Calling naar Agent:**
|
||||
- Tool calling = AI roept 1 tool aan, klaar
|
||||
- Agent = AI blijft tools aanroepen totdat de taak af is
|
||||
|
||||
**Het verschil is één parameter: `maxSteps`**
|
||||
|
||||
```typescript
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: `Je bent een cocktail party planner.
|
||||
Plan een compleet menu met alle details.`,
|
||||
messages,
|
||||
tools: { /* ... tools ... */ },
|
||||
maxSteps: 8 // ← Agent mag 8 tool-calls doen
|
||||
})
|
||||
```
|
||||
|
||||
#### Voorbeeld: Party Planner Agent
|
||||
|
||||
```typescript
|
||||
// app/api/party-planner/route.ts
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { streamText, tool } from 'ai'
|
||||
import { z } from 'zod'
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o'), // Gebruik slimmer model voor agent taken
|
||||
system: `Je bent een professionele cocktail party planner.
|
||||
|
||||
Wanneer iemand een feest wil plannen:
|
||||
1. Zoek eerst cocktails die passen bij de wensen
|
||||
2. Haal recepten op van de beste opties
|
||||
3. Denk aan non-alcoholische alternatieven
|
||||
4. Geef een compleet overzicht met ingrediënten
|
||||
|
||||
Wees proactief en denk mee.`,
|
||||
messages,
|
||||
tools: {
|
||||
searchByIngredient: tool({
|
||||
description: 'Zoek cocktails met een ingrediënt',
|
||||
parameters: z.object({
|
||||
ingredient: z.string()
|
||||
}),
|
||||
execute: async ({ ingredient }) => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${ingredient}`
|
||||
)
|
||||
return res.json()
|
||||
}
|
||||
}),
|
||||
|
||||
getCocktailDetails: tool({
|
||||
description: 'Haal recept details op',
|
||||
parameters: z.object({
|
||||
cocktailId: z.string()
|
||||
}),
|
||||
execute: async ({ cocktailId }) => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${cocktailId}`
|
||||
)
|
||||
return res.json()
|
||||
}
|
||||
}),
|
||||
|
||||
searchNonAlcoholic: tool({
|
||||
description: 'Zoek mocktails',
|
||||
parameters: z.object({}),
|
||||
execute: async () => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/filter.php?a=Non_Alcoholic`
|
||||
)
|
||||
return res.json()
|
||||
}
|
||||
}),
|
||||
|
||||
searchByCategory: tool({
|
||||
description: 'Zoek cocktails per categorie (Cocktail, Shot, Beer, etc.)',
|
||||
parameters: z.object({
|
||||
category: z.string()
|
||||
}),
|
||||
execute: async ({ category }) => {
|
||||
const res = await fetch(
|
||||
`https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=${category}`
|
||||
)
|
||||
return res.json()
|
||||
}
|
||||
})
|
||||
},
|
||||
maxSteps: 10 // Agent kan tot 10 tool calls doen
|
||||
})
|
||||
|
||||
return result.toDataStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
**Agent in actie:**
|
||||
```
|
||||
User: "Plan cocktails voor mijn verjaardagsfeest.
|
||||
15 mensen, een paar drinken geen alcohol,
|
||||
we houden van citrus smaken."
|
||||
|
||||
Agent stappen:
|
||||
1. searchByIngredient("lemon") → 12 cocktails
|
||||
2. searchByIngredient("lime") → 15 cocktails
|
||||
3. searchByIngredient("orange") → 10 cocktails
|
||||
4. searchNonAlcoholic() → 8 mocktails
|
||||
5. getCocktailDetails("11000") → Mojito recept
|
||||
6. getCocktailDetails("11007") → Margarita recept
|
||||
7. getCocktailDetails("12162") → Virgin Piña Colada recept
|
||||
8. getCocktailDetails("12316") → Lemonade recept
|
||||
|
||||
Output: Compleet party plan met:
|
||||
- 3 alcoholische cocktails met citrus
|
||||
- 2 mocktails voor niet-drinkers
|
||||
- Gecombineerde ingrediëntenlijst
|
||||
- Tips voor bereiding
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Gratis APIs voor Projecten
|
||||
|
||||
| API | Data | URL | Auth |
|
||||
|-----|------|-----|------|
|
||||
| TheCocktailDB | 636 cocktails, recepten | thecocktaildb.com/api.php | Geen (key=1) |
|
||||
| TheMealDB | 597 recepten, ingrediënten | themealdb.com/api.php | Geen (key=1) |
|
||||
| Open Trivia DB | 4000+ quiz vragen | opentdb.com/api_config.php | Geen |
|
||||
| REST Countries | Landen data | restcountries.com | Geen |
|
||||
| Open Library | Boeken data | openlibrary.org/developers | Geen |
|
||||
|
||||
---
|
||||
|
||||
### Best Practices
|
||||
|
||||
**Tool Design:**
|
||||
```typescript
|
||||
// ✅ Goed: Specifieke, duidelijke tools
|
||||
searchByIngredient: tool({
|
||||
description: 'Zoek cocktails die een specifiek ingrediënt bevatten',
|
||||
// ...
|
||||
})
|
||||
|
||||
// ❌ Slecht: Vage tool
|
||||
search: tool({
|
||||
description: 'Zoek iets',
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
**Agent System Prompts:**
|
||||
```typescript
|
||||
// ✅ Goed: Geef duidelijke instructies
|
||||
system: `Je bent een cocktail expert.
|
||||
|
||||
Wanneer je een vraag krijgt:
|
||||
1. Zoek eerst relevante cocktails
|
||||
2. Haal details op van de beste matches
|
||||
3. Geef persoonlijk advies
|
||||
|
||||
Wees proactief en denk mee met de gebruiker.`
|
||||
|
||||
// ❌ Slecht: Te vaag
|
||||
system: `Je bent een assistent.`
|
||||
```
|
||||
|
||||
**Error Handling in Tools:**
|
||||
```typescript
|
||||
execute: async ({ ingredient }) => {
|
||||
try {
|
||||
const res = await fetch(`...`)
|
||||
if (!res.ok) {
|
||||
return { error: 'Kon geen cocktails vinden' }
|
||||
}
|
||||
return res.json()
|
||||
} catch (error) {
|
||||
return { error: 'API niet beschikbaar' }
|
||||
}
|
||||
}
|
||||
```
|
||||
**Deployment:**
|
||||
- [ ] Deployed on Vercel
|
||||
- [ ] Working on production URL
|
||||
- [ ] Supabase configured
|
||||
- [ ] Environment variables secure
|
||||
- [ ] No errors in production
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel AI SDK (`ai` package)
|
||||
- Zod (parameter validatie)
|
||||
- Next.js API Routes
|
||||
- Externe APIs (TheCocktailDB, TheMealDB, etc.)
|
||||
- GitHub
|
||||
- Vercel
|
||||
- Chrome DevTools
|
||||
- Cursor
|
||||
- Peer reviewers
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
## Lesopdracht (3 uur)
|
||||
|
||||
### Bouw een AI Agent met Externe Data
|
||||
### Code Review & Polish Session
|
||||
|
||||
**Deel 1: Setup (15 min)**
|
||||
1. `npm install ai @ai-sdk/openai zod`
|
||||
2. Voeg `OPENAI_API_KEY` toe aan `.env.local`
|
||||
3. Kies je API: TheCocktailDB of TheMealDB
|
||||
**Deel 1: Peer Review (1 uur)**
|
||||
|
||||
**Deel 2: Basic Tool Calling (45 min)**
|
||||
1. Maak `/api/chat/route.ts`
|
||||
2. Implementeer 2 tools:
|
||||
- Zoek op ingrediënt
|
||||
- Haal details op
|
||||
3. Test: "Wat kan ik maken met [ingrediënt]?"
|
||||
Work in pairs or small groups:
|
||||
1. Exchange project URLs/repos
|
||||
2. Each person reviews another's work
|
||||
3. Take detailed notes
|
||||
4. Provide constructive feedback
|
||||
5. Discuss improvements
|
||||
|
||||
**Deel 3: Agent met maxSteps (45 min)**
|
||||
1. Voeg `maxSteps: 5` toe
|
||||
2. Voeg een 3e tool toe (bijv. zoek per categorie)
|
||||
3. Verbeter je system prompt voor agent gedrag
|
||||
4. Test: "Help me een menu plannen voor..."
|
||||
**Deel 2: Final Polish (1.5 uur)**
|
||||
|
||||
**Deel 4: Frontend (15 min)**
|
||||
1. Bouw chat UI met `useChat`
|
||||
2. Voeg loading indicator toe
|
||||
3. Test de complete flow
|
||||
Based on feedback:
|
||||
1. Fix identified bugs
|
||||
2. Implement suggested improvements
|
||||
3. Code cleanup
|
||||
4. Update documentation
|
||||
5. Final test in production
|
||||
|
||||
**Deel 3: Final Checks (30 min)**
|
||||
|
||||
Go through the submission checklist:
|
||||
1. Verify all items are done
|
||||
2. Test everything once more
|
||||
3. Make final commits
|
||||
4. Push to GitHub
|
||||
5. Screenshot for documentation
|
||||
|
||||
### Deliverable
|
||||
- Werkende agent met minimaal 3 tools
|
||||
- Chat interface
|
||||
- Screenshot van agent die meerdere tools aanroept
|
||||
- Peer review feedback received
|
||||
- All feedback items addressed
|
||||
- Final production-ready code
|
||||
- Complete documentation
|
||||
- Screenshot of final app
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk
|
||||
|
||||
### Bouw AI Feature voor Eindproject
|
||||
**Final submission preparation:**
|
||||
|
||||
**Deel 1: Agent Design (30 min)**
|
||||
1. **Complete ALL documentation:**
|
||||
- README with features and setup
|
||||
- PROMPT-LOG.md with 10+ prompts
|
||||
- AI-DECISIONS.md with 5+ decisions
|
||||
- Project state documented
|
||||
|
||||
Plan je agent voor de eindopdracht:
|
||||
- Welke externe API gebruik je?
|
||||
- Welke tools heeft je agent nodig? (minimaal 3)
|
||||
- Wat is de typische flow?
|
||||
2. **Final testing:**
|
||||
- Test all features in production
|
||||
- Check Lighthouse score
|
||||
- Verify mobile responsiveness
|
||||
- Check load times
|
||||
|
||||
Documenteer in `docs/AI-DECISIONS.md`
|
||||
3. **Code review:**
|
||||
- Ask classmates to review code
|
||||
- Ask docent for feedback
|
||||
- Fix any issues found
|
||||
- Final cleanup
|
||||
|
||||
**Deel 2: Implementatie (1 uur)**
|
||||
|
||||
Bouw de agent voor je eindproject:
|
||||
- Minimaal 3 tools
|
||||
- `maxSteps` van minimaal 3
|
||||
- Goede error handling
|
||||
- Relevante system prompt
|
||||
|
||||
**Deel 3: Integratie (30 min)**
|
||||
|
||||
Combineer met Supabase:
|
||||
- Sla user preferences op
|
||||
- Geef preferences mee als context aan agent
|
||||
- Sla conversation history op
|
||||
4. **Prepare for submission:**
|
||||
- Ensure Git history is clean
|
||||
- All commits have good messages
|
||||
- GitHub repo is public/accessible
|
||||
- Production URL is stable
|
||||
|
||||
### Deliverable
|
||||
- Werkende agent in eindproject
|
||||
- `docs/AI-DECISIONS.md` met agent design
|
||||
- Minimaal 5 prompts in `PROMPT-LOG.md`
|
||||
|
||||
---
|
||||
|
||||
## 💡 Eindopdracht
|
||||
|
||||
Heb je al nagedacht over je AI feature? Dit is het moment om je idee te bespreken met de docent en klasgenoten. Welke externe API ga je gebruiken? Welke tools heeft je agent nodig?
|
||||
- Final, polished application
|
||||
- All documentation complete
|
||||
- Code review completed
|
||||
- Ready for submission
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Vercel AI SDK installeren en configureren
|
||||
- Tools definiëren met Zod parameters
|
||||
- Tool Calling implementeren voor externe API integratie
|
||||
- Agents bouwen met `maxSteps` voor autonome taken
|
||||
- De juiste aanpak kiezen (basic chat vs tool calling vs agent)
|
||||
- Error handling implementeren in tools
|
||||
- Gratis externe APIs integreren in AI features
|
||||
- Code review uitvoeren volgens best practices
|
||||
- Peer feedback ontvangen en implementeren
|
||||
- Final polish toepassen op projecten
|
||||
- Production checklist doorlopen
|
||||
- Professional quality deliverables opleveren
|
||||
- Zelfstandig werk evalueren en verbeteren
|
||||
|
||||
Reference in New Issue
Block a user