# Bouwplan — AI Cliënt Assistent **Projectnaam:** Mini-ECD – AI Cliënt Assistent **Versie:** v1.0 **Datum:** 01-12-2025 **Auteur:** Colin Lit --- ## 1. Doel en context **Doel:** Uitbreiding van de bestaande AI Documentatie Assistent met cliënt-awareness. Wanneer een behandelaar in een cliëntdossier zit, kan de assistent vragen beantwoorden over díe specifieke cliënt. **Aanleiding:** Behandelaren besteden veel tijd aan het navigeren door verschillende schermen om informatie over een cliënt te verzamelen. Bij een overdracht of voorbereiding op een consult moeten zij rapportages doorbladeren, risico-assessments opzoeken, behandeladviezen teruglezen en screeningresultaten checken. **Referenties:** - PRD: `docs/specs/ai-integratie/prd-ai-client-assistent-v1.md` - FO: `docs/specs/ai-integratie/fo-ai-client-assistent-v1.md` - TO: `docs/specs/ai-integratie/to-ai-client-assistent-v1.md` --- ## 2. Uitgangspunten ### 2.1 Technische Stack - **Frontend:** Next.js 15 + React + Tailwind CSS - **Backend:** Next.js API Routes - **Database:** Supabase (PostgreSQL) met RLS - **AI/ML:** Claude claude-sonnet-4-20250514 (Anthropic) - **Hosting:** Vercel - **Auth:** Supabase Auth - **Streaming:** Server-Sent Events (SSE) ### 2.2 Projectkaders - **Bouwtijd:** ~8-12 uur (MVP) - **Team:** 1 developer - **Data:** Bestaande demo-data (21 rapportages, 9 intakes, 5 screenings) - **Doel:** Werkende cliënt-aware chat in bestaande docs-chat widget ### 2.3 Bestaande Infrastructuur (Hergebruik) | Component | Status | Hergebruik | |-----------|--------|------------| | DocsChatWidget | ✅ Compleet | ~80% | | Streaming (SSE) | ✅ Werkt | 100% | | PatientContext | ✅ Werkt | 100% | | Rate limiting | ✅ Werkt | 100% | | Chat suggestions | ✅ Werkt | Uitbreiden | | `/api/reports` | ✅ Bestaat | Direct bruikbaar | | `/api/intakes` | ✅ Bestaat | Direct bruikbaar | | `/api/screenings` | ✅ Bestaat | Direct bruikbaar | ### 2.4 Programmeer Uitgangspunten - **DRY:** Hergebruik bestaande docs-chat componenten - **KISS:** Minimale wijzigingen aan bestaande code - **SOC:** Nieuwe modules in `lib/docs/` voor client-specifieke logica - **YAGNI:** Alleen MVP features, geen toekomstige uitbreidingen --- ## 3. Epics & Stories Overzicht | Epic ID | Titel | Doel | Status | Stories | |---------|-------|------|--------|---------| | E1 | Backend Modules | Context loader, detector, prompt builder | ✅ Done | 3 | | E2 | API Uitbreiding | Chat endpoint uitbreiden met clientId | ✅ Done | 2 | | E3 | Frontend Uitbreiding | Indicator, suggestions, hook aanpassing | ✅ Done | 3 | | E4 | Testing & Refinement | Integratie testen, prompt tuning | ✅ Done | 2 | --- ## 4. Epics & Stories (Uitwerking) ### Epic 1 — Backend Modules **Epic Doel:** Nieuwe modules voor cliënt-context laden, vraagtype detectie en prompt building. | Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP | |----------|--------------|---------------------|--------|------------------|----| | E1.S1 | Client Context Loader | Laadt patient + reports + intakes + screenings uit Supabase | ✅ | — | 3 | | E1.S2 | Question Type Detector | Detecteert 'client' vs 'documentation' vs 'ambiguous' | ✅ | — | 2 | | E1.S3 | Client Prompt Builder | Bouwt system prompt met cliënt-context | ✅ | E1.S1 | 2 | **Technical Notes:** **E1.S1 - Client Context Loader** (`lib/docs/client-context-loader.ts`) ```typescript interface ClientContext { patient: { name: string; birthDate: string; status: string } reports: Array<{ type: string; content: string; date: string }> intakes: Array<{ title: string; treatmentAdvice: object; status: string }> screening: { requestForHelp: string; decision: string } | null riskAssessments: Array<{ type: string; level: string; rationale: string }> } // Directe Supabase queries (niet via HTTP voor performance) // Parallel laden: Promise.all([reports, intakes, screening, risks]) // Laatste 5 rapportages, 3 intakes, 1 screening ``` **E1.S2 - Question Type Detector** (`lib/docs/question-type-detector.ts`) ```typescript const CLIENT_KEYWORDS = [ 'rapportage', 'risico', 'behandeladvies', 'screening', 'hulpvraag', 'samenvatting', 'dossier', 'deze cliënt' ] const DOC_KEYWORDS = [ 'hoe', 'waar', 'wat is', 'tutorial', 'handleiding', 'functie', 'knop', 'menu', 'systeem', 'epd' ] // Return: 'client' | 'documentation' | 'ambiguous' ``` **E1.S3 - Client Prompt Builder** (`lib/docs/client-prompt-builder.ts`) - Strikte regels: alleen beschikbare data, geen hallucinatie - Geen medisch advies - Beknopt en professioneel - Max 4000 tokens context --- ### Epic 2 — API Uitbreiding **Epic Doel:** Bestaande chat endpoint uitbreiden met cliënt-awareness. | Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP | |----------|--------------|---------------------|--------|------------------|----| | E2.S1 | Request schema uitbreiden | Accepteert optioneel `clientId` parameter | ✅ | E1.S1-S3 | 2 | | E2.S2 | Routing logica | Bij client-vraag: client prompt, bij doc-vraag: bestaande flow | ✅ | E2.S1 | 3 | **Technical Notes:** **E2.S1 - Request Schema** (`app/api/docs/chat/route.ts`) ```typescript // Huidige schema uitbreiden: { messages: Array<{ role: 'user' | 'assistant', content: string }>, userMessage: string, clientId?: string // Nieuw: UUID van actieve patiënt } ``` **E2.S2 - Routing Logica** ```typescript // Pseudocode: const questionType = detectQuestionType(userMessage, !!clientId) if (questionType === 'client' && clientId) { const context = await loadClientContext(clientId) const systemPrompt = buildClientPrompt(context, userMessage) // Skip ai_events logging (privacy) } else { // Bestaande documentatie flow const categories = detectCategories(userMessage) const knowledgeSections = await loadKnowledgeSections(categories) const systemPrompt = buildSystemPrompt(knowledgeSections) } ``` --- ### Epic 3 — Frontend Uitbreiding **Epic Doel:** UI aanpassingen voor cliënt-indicator en dynamische suggestions. | Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP | |----------|--------------|---------------------|--------|------------------|----| | E3.S1 | useDocsChat hook uitbreiden | Stuurt clientId mee, exposed hasPatientContext | ✅ | E2.S2 | 2 | | E3.S2 | Cliënt Indicator | Header toont "Dossier: [Naam]" wanneer in dossier | ✅ | E3.S1 | 1 | | E3.S3 | Dynamische Suggestions | Cliënt-suggesties in dossier, doc-suggesties daarbuiten | ✅ | E3.S1 | 2 | **Technical Notes:** **E3.S1 - Hook Uitbreiding** (`components/docs-chat/use-docs-chat.ts`) ```typescript import { usePatientContext } from '@/app/epd/components/patient-context' // In hook: const { patient } = usePatientContext() // Bij sendMessage: body: JSON.stringify({ messages: recentMessages, userMessage, clientId: patient?.id // Meesturen als patient actief }) // Exposed voor UI: return { ...state, hasPatientContext: !!patient, patientName: patient?.name?.[0]?.text || null } ``` **E3.S2 - Cliënt Indicator** (`components/docs-chat/docs-chat-widget.tsx`) ```tsx {hasPatientContext && patientName && (