Files
triqura-ecd/docs/intent/samenspel-tip-ecd.html
colinislit 6419398060 docs: discussiestuk samenspel TIP-ECD, sessielog 14 juli en releasenote-screenshots
- docs/intent/samenspel-tip-ecd.html: laag-of-platform discussiestuk voor
  de werksessie over de TIP-koppeling (twee modellen, drie routes,
  API-mapping, beslisvragen)
- docs/sessions/2026-07-14-sessielog.md: besluiten, reviewbevindingen en
  uitgevoerde opschoning van vandaag

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 15:32:15 +02:00

664 lines
29 KiB
HTML

<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Samenspel TIP en GGZ-ECD</title>
<style>
:root {
--bg: #F6F8F8;
--surface: #FFFFFF;
--ink: #1C2B2A;
--muted: #5A6E6B;
--line: #DAE3E1;
--teal: #0F766E;
--teal-soft: #E4F1EF;
--teal-ink: #0B5A54;
--amber: #B45309;
--amber-soft: #F9EEDF;
--amber-ink: #8F4407;
--warn: #9A3412;
--chip-ink: #FFFFFF;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0E1615;
--surface: #16211F;
--ink: #E4ECEA;
--muted: #91A5A1;
--line: #263431;
--teal: #3CB8A9;
--teal-soft: #12302C;
--teal-ink: #7DD6CA;
--amber: #E09A3F;
--amber-soft: #33260F;
--amber-ink: #EDBA75;
--warn: #E8825A;
--chip-ink: #0E1615;
}
}
:root[data-theme="light"] {
--bg: #F6F8F8; --surface: #FFFFFF; --ink: #1C2B2A; --muted: #5A6E6B;
--line: #DAE3E1; --teal: #0F766E; --teal-soft: #E4F1EF; --teal-ink: #0B5A54;
--amber: #B45309; --amber-soft: #F9EEDF; --amber-ink: #8F4407;
--warn: #9A3412; --chip-ink: #FFFFFF;
}
:root[data-theme="dark"] {
--bg: #0E1615; --surface: #16211F; --ink: #E4ECEA; --muted: #91A5A1;
--line: #263431; --teal: #3CB8A9; --teal-soft: #12302C; --teal-ink: #7DD6CA;
--amber: #E09A3F; --amber-soft: #33260F; --amber-ink: #EDBA75;
--warn: #E8825A; --chip-ink: #0E1615;
}
* { box-sizing: border-box; }
body {
background: var(--bg);
color: var(--ink);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 16px;
line-height: 1.65;
margin: 0;
-webkit-font-smoothing: antialiased;
}
.page {
max-width: 860px;
margin: 0 auto;
padding: 56px 28px 96px;
}
h1, h2, h3 {
font-family: Charter, "Iowan Old Style", Georgia, "Times New Roman", serif;
text-wrap: balance;
line-height: 1.2;
margin: 0;
}
h1 { font-size: 2.35rem; font-weight: 700; letter-spacing: -0.01em; }
h2 { font-size: 1.5rem; font-weight: 700; margin-top: 0; }
h3 { font-size: 1.1rem; font-weight: 700; }
p { margin: 0 0 1em; max-width: 68ch; }
strong { font-weight: 650; }
.eyebrow {
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--teal);
margin-bottom: 14px;
}
.meta {
display: flex;
flex-wrap: wrap;
gap: 8px 24px;
margin-top: 20px;
padding-top: 18px;
border-top: 1px solid var(--line);
font-size: 0.84rem;
color: var(--muted);
}
.meta b { color: var(--ink); font-weight: 600; }
section { margin-top: 64px; }
.sec-head {
display: flex;
align-items: baseline;
gap: 16px;
margin-bottom: 20px;
}
.sec-num {
font-family: Charter, Georgia, serif;
font-size: 1.5rem;
font-weight: 700;
color: var(--teal);
font-variant-numeric: tabular-nums;
flex-shrink: 0;
}
.lede {
font-family: Charter, "Iowan Old Style", Georgia, serif;
font-size: 1.22rem;
line-height: 1.55;
max-width: 62ch;
}
.callout {
border-left: 3px solid var(--teal);
background: var(--teal-soft);
padding: 16px 20px;
border-radius: 0 8px 8px 0;
margin: 24px 0;
max-width: 68ch;
}
.callout p { margin: 0; }
.callout.amber { border-left-color: var(--amber); background: var(--amber-soft); }
/* Chips voor systeem-aanduiding */
.chip {
display: inline-block;
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.08em;
padding: 2px 9px;
border-radius: 99px;
vertical-align: 1px;
}
.chip.ecd { background: var(--teal); color: var(--chip-ink); }
.chip.tip { background: var(--amber); color: var(--chip-ink); }
/* ============ Diagram: twee modellen ============ */
.models {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin: 28px 0;
}
@media (max-width: 700px) { .models { grid-template-columns: 1fr; } }
.model {
background: var(--surface);
border: 1px solid var(--line);
border-radius: 12px;
padding: 20px;
display: flex;
flex-direction: column;
}
.model-title {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 4px;
}
.model-sub {
font-family: Charter, Georgia, serif;
font-size: 1.05rem;
font-weight: 700;
margin-bottom: 16px;
}
.sysbox {
border-radius: 8px;
padding: 10px 14px;
font-size: 0.85rem;
font-weight: 600;
text-align: center;
}
.sysbox small { display: block; font-weight: 400; font-size: 0.76rem; opacity: 0.85; margin-top: 2px; }
.sysbox.tipbox { background: var(--amber-soft); border: 1.5px solid var(--amber); color: var(--amber-ink); }
.sysbox.ecdbox { background: var(--teal-soft); border: 1.5px solid var(--teal); color: var(--teal-ink); }
.sysbox .inner {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
margin-top: 8px;
}
.sysbox .inner span {
font-size: 0.7rem;
font-weight: 500;
padding: 2px 8px;
border-radius: 5px;
background: var(--surface);
border: 1px solid var(--line);
color: var(--ink);
}
.flow-arrow {
text-align: center;
color: var(--muted);
font-size: 0.74rem;
padding: 6px 0;
line-height: 1.4;
}
.flow-arrow b { color: var(--ink); }
.duo-arrows {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
padding: 6px 0;
font-size: 0.74rem;
color: var(--muted);
text-align: center;
}
.model-caption {
margin-top: auto;
padding-top: 14px;
font-size: 0.82rem;
color: var(--muted);
border-top: 1px dashed var(--line);
margin-bottom: 0;
}
/* ============ Stappenflow ============ */
.steps { margin: 28px 0; display: flex; flex-direction: column; gap: 0; }
.step {
display: grid;
grid-template-columns: 34px 1fr;
gap: 16px;
position: relative;
padding-bottom: 22px;
}
.step:not(:last-child)::before {
content: "";
position: absolute;
left: 16px;
top: 34px;
bottom: 0;
width: 2px;
background: var(--line);
}
.step-dot {
width: 34px; height: 34px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.85rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
flex-shrink: 0;
z-index: 1;
}
.step-dot.ecd { background: var(--teal); color: var(--chip-ink); }
.step-dot.tip { background: var(--amber); color: var(--chip-ink); }
.step-body { font-size: 0.92rem; padding-top: 5px; max-width: 62ch; }
.step-body .who { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; }
.step-body .who.ecd { color: var(--teal); }
.step-body .who.tip { color: var(--amber); }
.step-body p { margin: 2px 0 0; }
.state-note {
margin-top: 8px;
font-size: 0.8rem;
background: var(--amber-soft);
color: var(--amber-ink);
border-radius: 6px;
padding: 8px 12px;
display: inline-block;
}
/* ============ Tabellen ============ */
.tablewrap { overflow-x: auto; margin: 24px 0; border: 1px solid var(--line); border-radius: 10px; }
table {
border-collapse: collapse;
width: 100%;
font-size: 0.87rem;
background: var(--surface);
}
th, td {
text-align: left;
padding: 11px 16px;
border-bottom: 1px solid var(--line);
vertical-align: top;
}
th {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--muted);
background: var(--bg);
white-space: nowrap;
}
tr:last-child td { border-bottom: none; }
td.yes { color: var(--teal-ink); font-weight: 600; white-space: nowrap; }
td.no { color: var(--warn); font-weight: 600; white-space: nowrap; }
td.partial { color: var(--amber-ink); font-weight: 600; }
/* ============ Routes ============ */
.routes { display: flex; flex-direction: column; gap: 20px; margin: 28px 0; }
.route {
background: var(--surface);
border: 1px solid var(--line);
border-radius: 12px;
padding: 24px;
position: relative;
}
.route.recommended { border: 1.5px solid var(--teal); }
.route-badge {
position: absolute;
top: -11px;
right: 20px;
background: var(--teal);
color: var(--chip-ink);
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.09em;
text-transform: uppercase;
padding: 3px 12px;
border-radius: 99px;
}
.route-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 6px; flex-wrap: wrap; }
.route-num {
font-family: Charter, Georgia, serif;
font-size: 1.05rem;
font-weight: 700;
color: var(--muted);
}
.route-oneliner { color: var(--muted); font-size: 0.92rem; margin-bottom: 16px; font-style: italic; }
.route-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 24px;
font-size: 0.88rem;
}
@media (max-width: 640px) { .route-grid { grid-template-columns: 1fr; } }
.route-cell .lbl {
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 3px;
}
.route-cell p { margin: 0; }
/* ============ Beslisvragen ============ */
.questions { counter-reset: q; display: flex; flex-direction: column; gap: 14px; margin-top: 24px; }
.q {
counter-increment: q;
background: var(--surface);
border: 1px solid var(--line);
border-radius: 10px;
padding: 16px 20px 16px 58px;
position: relative;
max-width: 100%;
}
.q::before {
content: counter(q);
position: absolute;
left: 18px;
top: 15px;
width: 26px; height: 26px;
border-radius: 50%;
background: var(--teal-soft);
color: var(--teal-ink);
font-weight: 700;
font-size: 0.85rem;
display: flex;
align-items: center;
justify-content: center;
}
.q b { display: block; margin-bottom: 2px; }
.q p { margin: 0; font-size: 0.9rem; color: var(--muted); }
.footer-note {
margin-top: 72px;
padding-top: 20px;
border-top: 1px solid var(--line);
font-size: 0.8rem;
color: var(--muted);
max-width: 68ch;
}
</style>
</head>
<body>
<div class="page">
<header>
<div class="eyebrow">Discussiestuk · Triqura</div>
<h1>Het samenspel tussen<br>TIP en het GGZ&#8209;ECD</h1>
<div class="meta">
<span><b>Voor</b> — werksessie Colin &amp; Joshua</span>
<span><b>Datum</b> — 14 juli 2026</span>
<span><b>Status</b> — ter bespreking, geen besluit</span>
</div>
</header>
<section>
<div class="sec-head"><span class="sec-num">1</span><h2>Constatering</h2></div>
<p class="lede">We bouwen aan twee systemen die samen één geheel moeten vormen: het GGZ&#8209;ECD als eerste toepassing, TIP als het intent&#8209;platform eronder. We hebben allebei dezelfde vraag op tafel — welke API&#8217;s hebben we nodig? — maar die is pas te beantwoorden als we samen de rolverdeling kiezen. Er leven nu twee verschillende beelden van hoe de systemen samenwerken, en die leiden tot verschillende API&#8217;s, verschillende datamodellen en een andere taakverdeling tussen de teams.</p>
<div class="callout">
<p><strong>De kernvraag van dit stuk:</strong> hoe verdelen ECD en TIP het werk — TIP als beslisplatform dat het ECD voedt met gegevens, of TIP als intent&#8209;laag die met het ECD meekijkt? Die keuze bepaalt óók het verhaal van het platform richting volgende domeinen. Een gezamenlijke productkeuze dus, geen techniekvraag van één van beide kanten.</p>
</div>
</section>
<section>
<div class="sec-head"><span class="sec-num">2</span><h2>Aanleiding</h2></div>
<p>Er komen drie sporen samen:</p>
<p><strong>Het ECD wordt opnieuw opgebouwd.</strong> Het huidige prototype leunt op Supabase en FHIR&#8209;conventies die eruit gaan. Er komt een eigen PostgreSQL&#8209;datamodel onder, met voorbereiding op pgvector (semantisch zoeken) en Neo4j (ZPM&#8209;relaties). Het moment om de architectuur goed te snijden is nú.</p>
<p><strong>Het intent&#8209;systeem komt uit TIP.</strong> De oorspronkelijke Cortex&#8209;architectuur ging uit van een intent-motor als TypeScript&#8209;bibliotheek ín de ECD&#8209;app (<code>lib/cortex/</code>). TIP bestaat inmiddels als zelfstandig platform (Python&#8209;services, eigen runtime) en is domein&#8209;agnostisch opgezet: het GGZ&#8209;ECD is de eerste toepassing, andere domeinen moeten volgen. Het ECD bewijst het platform; het platform draagt het ECD.</p>
<p><strong>De gedeelde vraag: &#8220;welke API&#8217;s hebben we eigenlijk nodig?&#8221;</strong> Die vraag speelt aan beide kanten en is niet te beantwoorden zonder eerst samen de rolverdeling te kiezen. Bij het naast elkaar leggen van beide codebases bleek dat de twee beelden van die rolverdeling (§3) nu nog uiteenlopen — dat is geen probleem, maar wel iets om expliciet te maken vóór we contracten vastleggen.</p>
</section>
<section>
<div class="sec-head"><span class="sec-num">3</span><h2>Twee mentale modellen</h2></div>
<p>Legenda: <span class="chip ecd">ECD</span> klinische applicatie &amp; dossier &nbsp;·&nbsp; <span class="chip tip">TIP</span> intent-platform.</p>
<div class="models">
<div class="model">
<div class="model-title">Model A — het beeld</div>
<div class="model-sub">TIP als laag bovenop het ECD</div>
<div class="sysbox tipbox">TIP<small>vertaalt taal → intent, geeft suggesties</small></div>
<div class="duo-arrows">
<span>tekst / spraak ↑</span>
<span>↓ intent + suggestie</span>
</div>
<div class="sysbox ecdbox">ECD<small>draait volledig zelfstandig</small>
<div class="inner"><span>UI</span><span>logica</span><span>regels</span><span>database</span></div>
</div>
<p class="model-caption">TIP heeft geen eigen administratie. Trek je TIP eruit, dan werkt het ECD nog steeds — alleen zonder taalinterface. Dit is het model uit het oorspronkelijke Cortex&#8209;architectuurdocument (vgl. &#8220;AI&#8209;laag boven Chipsoft/Nexus&#8221;).</p>
</div>
<div class="model">
<div class="model-title">Model B — hoe TIP gebouwd is</div>
<div class="model-sub">Het ECD aangesloten op TIP</div>
<div class="sysbox ecdbox">ECD<small>registratie &amp; klinische feiten</small>
<div class="inner"><span>UI</span><span>klinisch dossier</span></div>
</div>
<div class="duo-arrows">
<span>artifacts &amp; events ↓</span>
<span>↑ intents &amp; taken</span>
</div>
<div class="sysbox tipbox">TIP<small>eigen database, eigen dossier-state</small>
<div class="inner"><span>dossiers</span><span>workspaces</span><span>IE&#8217;s</span><span>intentregels</span><span>scenario&#8217;s</span></div>
</div>
<p class="model-caption">TIP werkt pas als het gevoed wordt: documenten, gebeurtenissen en gegevens moeten naar TIP gepusht worden. TIP houdt zelf bij waar elke casus staat. Trek je de datafeed eruit, dan is TIP blind.</p>
</div>
</div>
<p>Beide paden in TIP — het gestructureerde pad (intentregels over Information Elements) en het ongestructureerde pad (vrije tekst via <code>/detect</code>) — leveren dezelfde intent op. Maar alleen het ongestructureerde pad werkt zonder datafeed. De kracht van TIP — regels, scenario&#8217;s, zorgpaden — zit in het gestructureerde pad, en dat vereist Model&nbsp;B.</p>
<div class="callout amber">
<p><strong>Deze opzet is een logische ontwerpkeuze.</strong> Elke beslislaag moet de data kunnen zien waarover hij beslist. De Information&#8209;Element&#8209;laag is precies wat TIP domein&#8209;agnostisch maakt: het platform hoeft geen enkel bronsysteem te kennen, zolang bronsystemen hun gegevens als IE&#8217;s aanleveren. Er hoort alleen een consequentie bij die we samen moeten inplannen: <em>een toepassing op TIP aansluiten betekent altijd een datafeed naar TIP bouwen</em> — integratiewerk aan beide kanten, geen laag die je er los oplegt.</p>
</div>
</section>
<section>
<div class="sec-head"><span class="sec-num">4</span><h2>Voorbeeld: de verwijsbrief-flow</h2></div>
<p>Hoe Model B er in de praktijk uitziet, stap voor stap. Let op waar de state terechtkomt.</p>
<div class="steps">
<div class="step">
<div class="step-dot ecd">1</div>
<div class="step-body">
<span class="who ecd">ECD</span>
<p>Een verwijsbrief komt binnen (ZorgDomein, e-mail, upload). Het ECD slaat de brief op in het klinisch dossier en stuurt hem als <strong>artifact</strong> door naar TIP.</p>
</div>
</div>
<div class="step">
<div class="step-dot tip">2</div>
<div class="step-body">
<span class="who tip">TIP</span>
<p>TIP maakt in zijn eigen database een workspace <code>referral</code> aan en extraheert Information Elements: <em>verwijzer, verwijsreden, urgentie</em>.</p>
<span class="state-note">State in TIP: dossier X · workspace &#8220;referral&#8221; · 3 IE&#8217;s gevuld</span>
</div>
</div>
<div class="step">
<div class="step-dot tip">3</div>
<div class="step-body">
<span class="who tip">TIP</span>
<p>Een intentregel vuurt: <em>&#8220;urgentie hoog én geen intake gepland → intent: intake inplannen&#8221;</em>. Het scenario zet een menselijke taak klaar — TIP voert nooit zelf uit.</p>
<span class="state-note">State in TIP: intent gevuurd · taak open · wacht op behandelaar</span>
</div>
</div>
<div class="step">
<div class="step-dot ecd">4</div>
<div class="step-body">
<span class="who ecd">ECD</span>
<p>Het ECD toont de taak. De behandelaar bevestigt (human&#8209;in&#8209;the&#8209;loop) en de intake&#8209;afspraak wordt in het ECD vastgelegd — het klinische feit leeft in het ECD.</p>
</div>
</div>
<div class="step">
<div class="step-dot ecd">5</div>
<div class="step-body">
<span class="who ecd">ECD</span>
<p>Het ECD meldt de voltooiing terug aan TIP als <strong>event</strong>, zodat TIP weet dat de taak is afgerond en de procesfase verschuift.</p>
<span class="state-note">State in TIP: fase verwijzing afgerond · intake gepland</span>
</div>
</div>
</div>
<h3>Het gevolg: twee administraties over dezelfde patiënt</h3>
<div class="tablewrap">
<table>
<thead>
<tr><th></th><th>ECD (klinische database)</th><th>TIP (platform-database)</th></tr>
</thead>
<tbody>
<tr>
<td><strong>Bevat</strong></td>
<td>Klinische feiten: rapportages, afspraken, diagnoses, de brief zelf</td>
<td>Proces-state: fase, workspaces, IE&#8217;s, gevuurde intents, open taken</td>
</tr>
<tr>
<td><strong>Bron van waarheid voor</strong></td>
<td>Het medisch dossier</td>
<td>&#8220;Waar staat het proces en wat moet er gebeuren&#8221;</td>
</tr>
</tbody>
</table>
</div>
<p>Zolang die scheiding scherp is — <strong>ECD&nbsp;=&nbsp;klinische feiten, TIP&nbsp;=&nbsp;proces- en beslislogica</strong> — is dit gezond. Het risico ontstaat waar hetzelfde feit op twee plekken leeft. &#8220;Intake gepland op 14&nbsp;juli&#8221; bestaat als afspraak in het ECD én als IE in TIP. Wordt de afspraak in het ECD verzet, dan moet er een event naar TIP — anders beslist TIP op verouderde informatie. Per gegeven moet dus vastliggen <em>wie eigenaar is</em>; de ander kent het alleen als afgeleide kopie.</p>
</section>
<section>
<div class="sec-head"><span class="sec-num">5</span><h2>Drie routes</h2></div>
<div class="routes">
<div class="route">
<div class="route-head"><span class="route-num">Route 1</span><h3>Alleen <code>/detect</code> — TIP als echte laag</h3></div>
<p class="route-oneliner">Het oorspronkelijke beeld: tekst in, intent uit, verder niets.</p>
<div class="route-grid">
<div class="route-cell"><div class="lbl">Wat het betekent</div><p>Het ECD roept alleen de intent&#8209;detectieservice aan. Alle state, regels, nudges en procesbewaking worden in het ECD zelf gebouwd (zoals in het oorspronkelijke Cortex&#8209;ontwerp).</p></div>
<div class="route-cell"><div class="lbl">Voordeel</div><p>Dun, stateless contract. Geen synchronisatievraagstuk. ECD blijft volledig autonoom; TIP&#8209;uitval betekent alleen &#8220;geen taalinterface&#8221;.</p></div>
<div class="route-cell"><div class="lbl">Consequentie</div><p>We gebruiken ~10% van het platform en bouwen intentregels, scenario&#8217;s en taken dubbel in het ECD. Twee regelmotoren in twee talen die uit elkaar groeien.</p></div>
<div class="route-cell"><div class="lbl">Wat het van beide kanten vraagt</div><p>TIP-kant vrijwel niets — <code>/detect</code> bestaat al. ECD-kant het meeste werk: alle beslislogica zelf bouwen. En de platformbelofte blijft onbeproefd.</p></div>
</div>
</div>
<div class="route">
<div class="route-head"><span class="route-num">Route 2</span><h3>TIP als procesbrein — volledig Model B</h3></div>
<p class="route-oneliner">Het ECD wordt registratie + UI; TIP doet alle beslislogica.</p>
<div class="route-grid">
<div class="route-cell"><div class="lbl">Wat het betekent</div><p>Elk relevant document en elke gebeurtenis gaat naar TIP. TIP bewaakt fases, evalueert regels, zet taken klaar. Het ECD toont en registreert.</p></div>
<div class="route-cell"><div class="lbl">Voordeel</div><p>TIP&#8217;s volle kracht: zorgpaden, intentregels, audit&#8209;chain. Regels wijzigen zonder ECD&#8209;deployment. Sterkste bewijs voor TIP&#8217;s platformbelofte.</p></div>
<div class="route-cell"><div class="lbl">Consequentie</div><p>ECD&#8209;datamodel en TIP&#8217;s dossiermodel moeten sámen ontworpen worden — geen twee projecten meer, maar één systeem in twee repo&#8217;s. Eigenaarschap per gegeven en de eventfeed moeten vanaf dag één kloppen. Grote wederzijdse afhankelijkheid, nog vóór we het samenspel in het klein hebben beproefd.</p></div>
<div class="route-cell"><div class="lbl">Wat het van beide kanten vraagt</div><p>ECD-kant: een volledige datafeed (artifacts, events) en taak-UI. TIP-kant: stabiele push&#8209;API, GGZ&#8209;workspace&#8209;typen en beschikbaarheidsafspraken — het ECD leunt in dit model op het platform.</p></div>
</div>
</div>
<div class="route recommended">
<span class="route-badge">Aanbevolen</span>
<div class="route-head"><span class="route-num">Route 3</span><h3>Groeipad — starten met <code>/detect</code> + één gestructureerde flow</h3></div>
<p class="route-oneliner">Klein beginnen op het pad naar Model B, met een echte proef van de datafeed.</p>
<div class="route-grid">
<div class="route-cell"><div class="lbl">Wat het betekent</div><p>Fase 1: <code>/detect</code> voor de taalinterface. Fase 2: één flow gestructureerd via TIP — instroom (verwijsbrief → intake), precies de flow uit §4. Chat en entity resolution blijven bewust in het ECD. Pas daarna per flow uitbreiden.</p></div>
<div class="route-cell"><div class="lbl">Voordeel</div><p>Het dubbele&#8209;administratie&#8209;vraagstuk wordt in het klein beproefd vóór het hele ECD eraan hangt. Het API&#8209;contract groeit mee met bewezen behoefte in plaats van vooraf gegokt. Beide teams houden tempo.</p></div>
<div class="route-cell"><div class="lbl">Consequentie</div><p>Tijdelijk hybride: sommige logica in het ECD, sommige in TIP. Vereist discipline om per flow expliciet te besluiten wáár die landt — anders ontstaat sluipenderwijs alsnog dubbeling.</p></div>
<div class="route-cell"><div class="lbl">Wat het van beide kanten vraagt</div><p>TIP-kant: <code>/detect</code> (bestaat) + artifact&#8209; en event&#8209;push voor één workspace&#8209;type (<code>referral</code>) en een taken&#8209;endpoint. ECD-kant: de feed voor die ene flow bouwen en taken tonen &amp; afmelden in de UI. Samen: eigenaarschap vastleggen voor de gegevens in deze flow.</p></div>
</div>
</div>
</div>
<p>De snijlijn die in alle routes overeind blijft: <strong>TIP kent geen patiëntnamen en geen schermen; het ECD kent geen intentregels en geen scenario&#8217;s.</strong> Entity resolution (&#8220;jan&#8221; → patiënt&nbsp;#427) vereist toegang tot het patiëntenbestand en hoort daarmee aan de ECD&#8209;kant — of het ECD stuurt kandidaten mee in de request.</p>
</section>
<section>
<div class="sec-head"><span class="sec-num">6</span><h2>Het samenspel per flow: wie levert wat</h2></div>
<p>Afgeleid uit de bestaande gebruikersflows van het ECD, gemapt op de huidige TIP&#8209;API. Dit is de feitelijke basis onder onze gedeelde API&#8209;vraag — per regel: wat de flow nodig heeft en waar dat vandaag staat.</p>
<div class="tablewrap">
<table>
<thead>
<tr><th>ECD-flow</th><th>Nodig van TIP</th><th>Status in TIP</th></tr>
</thead>
<tbody>
<tr>
<td>Commando typen/inspreken → intent + prefill</td>
<td><code>POST /detect</code></td>
<td class="yes">✓ bestaat</td>
</tr>
<tr>
<td>Verwijsbrief/document binnen → gegevens eruit</td>
<td>Artifact-push + IE-extractie in workspace</td>
<td class="yes">✓ bestaat (data layer)</td>
</tr>
<tr>
<td>Na actie → vervolgsuggestie (nudge)</td>
<td>Event-push → intentregels → taak terug</td>
<td class="partial">△ model bestaat; push-API vanuit het ECD moet in het contract</td>
</tr>
<tr>
<td>Bevestiging behandelaar (human-in-the-loop)</td>
<td><code>/human-gates</code>, taken ophalen &amp; afmelden</td>
<td class="yes">✓ bestaat</td>
</tr>
<tr>
<td>Beheer: intents, regels, scenario&#8217;s configureren</td>
<td><code>/intents</code>, <code>/rules</code>, <code>/contexts</code>, <code>/scenarios</code></td>
<td class="yes">✓ bestaat</td>
</tr>
<tr>
<td>Audit-inzage</td>
<td><code>/audit/events</code>, <code>/audit/chain</code></td>
<td class="yes">✓ bestaat</td>
</tr>
<tr>
<td>Chat (streaming, conversationeel)</td>
<td></td>
<td class="no">✗ nog nergens belegd — samen kiezen: ECD-kant of platform-roadmap (<code>ai-engine</code>)</td>
</tr>
<tr>
<td>Entity resolution (&#8220;jan&#8221; → patiënt #427)</td>
<td></td>
<td class="no">✗ hoort ECD-kant: vereist patiëntendata</td>
</tr>
<tr>
<td>Kennisbank / RAG (bronverwijzing bij suggestie)</td>
<td></td>
<td class="no">✗ nog niet zichtbaar in TIP</td>
</tr>
</tbody>
</table>
</div>
</section>
<section>
<div class="sec-head"><span class="sec-num">7</span><h2>Beslisvragen voor het gesprek</h2></div>
<div class="questions">
<div class="q">
<b>Welke rolverdeling kiezen we — platform of laag?</b>
<p>Sluiten toepassingen aan op TIP (Model B), of legt TIP zich als laag op toepassingen (Model A)? Deze keuze maken we samen: hij bepaalt het verhaal richting álle toekomstige domeinen, niet alleen dit ECD.</p>
</div>
<div class="q">
<b>Welke route kiezen we voor het GGZ-ECD?</b>
<p>Voorstel in dit stuk: route 3 — <code>/detect</code> plus de instroomflow als proef. Akkoord, of zien we het anders?</p>
</div>
<div class="q">
<b>Wie is eigenaar van welk gegeven?</b>
<p>Per gegeven vastleggen: leidend in het ECD of in TIP, en hoe de ander de kopie actueel houdt (events). Startpunt: de gegevens uit de instroomflow.</p>
</div>
<div class="q">
<b>Hoe ziet de push-API eruit — artifacts en events?</b>
<p>Het ontbrekende stuk contract voor route 3: hoe levert het ECD documenten en gebeurtenissen aan, en hoe haalt het taken op en meldt het ze af?</p>
</div>
<div class="q">
<b>Waar beleggen we chat, entity resolution en RAG?</b>
<p>Drie behoeftes die nu nergens belegd zijn. Bewust ECD-kant houden, of op de platform-roadmap (bijv. de <code>ai-engine</code>-service)? Per stuk samen besluiten.</p>
</div>
</div>
</section>
<p class="footer-note">Opgesteld ter voorbereiding op de werksessie over het samenspel tussen TIP en het GGZ-ECD. Gebaseerd op de TIP-documentatie (core model v1.0, architecture overview), de TIP-API zoals die er op 14 juli 2026 uitziet, en het Cortex-architectuurdocument v0.1. Geen besluit — gespreksagenda.</p>
</div>
</body>
</html>