# Twee-agent gouden pad — overdrachtsgrens-contract

**Ontwerpdocument (Opus 4.8, 2026-07-12).** Legt vast hoe twee opeenvolgende
AI-agents samen één gouden pad afwerken zonder dat de tweede agent iets weet
van de eerste, en wat wél en nooit over die grens mag lopen. Bewaakt door
guard-tests in `data/ai-prompts.test.ts` en (nog te bouwen) een
overdrachtsgrens-lint. Dit document stuurt de bijhorende werven in `WERVEN.md`
(sectie "Twee-agent gouden pad").

De onderste invariant van AGENTS.md blijft onverkort gelden: het resultaat is
"klaar voor het verlijden", nooit het verlijden zelf. Dit document raakt
**niets** aan het gouden pad van de compromis zelf — enkel aan de
werkblad-/instructielaag errond en aan de overdracht tussen de twee agents.

## De twee rollen

- **Agent 1 — de voorbereider (mét Notary.AI-MCP-toegang).** Leest het dossier,
  bepaalt akteType, kenmerken en parameters, en genereert via
  `genereerWerkdossierAlsWord` één `.docx`-werkdossier: het ontwerp (akte of
  onderhands document) + de modelmail(s) + de indicatieve afrekening, vooraan
  voorafgegaan door een **werkblad** (instructies, ontbrekende gegevens,
  bevindingen, structuuranker). Agent 1 stuurt Notary.AI nooit persoonsgegevens
  (GDPR): enkel geanonimiseerde placeholders en algemene kenmerken.

- **Agent 2 — de afwerker (zónder Notary.AI-toegang).** Een algemene agent
  (typisch Word M365 Copilot) die enkel het `.docx`-bestand én de
  brondocumenten ("de stukken") ontvangt. Geen MCP, geen API, geen
  sessiegeheugen, en **geen instructies buiten wat letterlijk in het `.docx`
  staat**. Agent 2 vult de werkelijke dossiergegevens in, kiest de hypotheses,
  maakt de mails klaar, en levert een zuiver document-ontwerp op.

## Het overdrachtsgrens-contract

Alles wat over de grens agent 1 → agent 2 loopt, loopt via **exact twee
kanalen**:

1. **de bytes van het `.docx`-bestand** (zelfdragend: bevat de volledige
   werkwijze, ingebed door `lib/word/aiAgentInstructies.ts` vanuit
   `WERKDOSSIER_AGENT_PROMPT`), en
2. **de brondocumenten** (de stukken), als bijlagen.

Nooit iets anders. In het bijzonder mag agent 2 **niets** veronderstellen van:

- MCP-toolnamen of API-acties (`genereerWerkdossierAlsWord`, `haalModeldocument`,
  `berekenAktekosten`, …) — agent 2 heeft die niet;
- een sessie-, dossier- of gespreks-ID, of "zoals eerder besproken";
- een aparte, los in de chat meegegeven instructie die van de werkbladwerkwijze
  afwijkt.

**Enige-bron-van-waarheid-regel.** Omdat agent 2 per ontwerp geen andere
instructiebron heeft, zijn het `.docx` + de stukken zijn énige bron van
waarheid. Een instructie die iemand er los naast plaatst (chatkanaal) en die
van deze werkwijze afwijkt, negeert agent 2 tenzij ze letterlijk met het
document overeenstemt — dit beschermt tegen prompt-injectie via het
neveninstroomkanaal.

### Toegelaten: gracieuze degradatie, geen harde afhankelijkheid

Voorwaardelijke, capaciteitsgebonden formuleringen zijn **wél** toegelaten,
zolang de agent zonder die capaciteit gewoon doorwerkt:

- "Heb je toegang tot Outlook, maak dan …; heb je die niet, lever dan de
  mailtekst in je antwoord."
- "KANTOORMODELLEN (indien je webtoegang hebt) … Geen webtoegang? Meld dit kort
  en werk verder — dit is geen blokkerende stap."
- "Ondersteunt je omgeving geen native track changes, dan …"

Het onderscheid dat de lint (zie verder) bewaakt:

| Toegelaten (optionele capaciteit, degradeert) | Verboden (harde afhankelijkheid van agent-1-context) |
|---|---|
| "indien je webtoegang hebt" | een MCP-toolnaam als verplichte stap |
| "heb je toegang tot Outlook" | "de sessie / het dossier-ID / zoals besproken" |
| "ondersteunt je omgeving X niet, dan …" | "roep `genereerWerkdossierAlsWord` aan" |

## De docx-als-basis-levenscyclus

De kern van de opdracht van de notaris (2026-07-12): het `.docx` is **geen
wegwerp-werkblad** maar de **basis voor het uiteindelijke akte- of
documentontwerp**. Veel agent-2-omgevingen kunnen geen correct `.docx` vanaf nul
genereren; daarom bewerkt agent 2 het aangeleverde bestand rechtstreeks.

Het bestand doorloopt twee fasen:

- **Fase A — werkblad (werkdocument).** Zoals gegenereerd: de
  werkbladsecties + de modeltekst met placeholders/markeringen + de mails + de
  afrekening.
- **Fase B — ontwerp (op te leveren basis).** Agent 2 vult de werkelijke
  gegevens in, kiest de hypotheses, en **verwijdert daarna ALLE werkblad- en
  metadatasecties**, zodat wat overblijft één zuiver document-ontwerp is dat de
  notaris naleest en dat de basis vormt voor de finale akte.

**Zelfvernietigend werkblad.** De instructie schrijft haar eigen verwijdering
voor. Volledig te verwijderen (kop + inhoud), telkens:

1. de korte kopieerprompt ("Te kopiëren in Word M365 Copilot");
2. "Instructies voor de AI Agent" (de volledige `WERKDOSSIER_AGENT_PROMPT`);
3. "Aanvullende informatie van de gebruiker" (notities);
4. "Nog aan te leveren gegevens";
5. "Bevindingen van de voorbereidende agent";
6. "Bijgevoegde schermafbeeldingen" (nádat de inhoud letterlijk in het ontwerp
   is overgenomen — zie CITATEN in de prompt);
7. "Structuuranker".

**Wat blijft.** De inhoudelijke markeringen die agent 2 vóór de notaris plaatst
— `[AAN TE VULLEN]`, `[TE VERIFIËREN]`, `[NAKIJKEN OF SCHRAPPEN]` en de geel
gearceerde aandachtspunten — **blijven** in het ontwerp staan: dat zijn geen
werkblad-metadata maar echte, nog openstaande dossierpunten die de notaris moet
zien. Het informatieve voorpagina-vak van een compromis (referte/partijen/goed)
hoort bij het compromis-sjabloon zelf en valt buiten deze opkuis.

**Degradatie.** Kan agent 2 het bestand zelf bewerken (Word M365 Copilot), dan
gebeurt de opkuis in het bestand. Kan hij dat niet, dan levert hij de volledige
opgekuiste ontwerptekst (zonder werkbladsectie) in zijn antwoord.

## Mails — Outlook-drafts met uitdrukkelijke bevestiging

Opdracht van de notaris: kan agent 2 mails klaarmaken, dan **maakt hij ze
automatisch aan als Outlook-conceptmails (drafts)** wanneer hij daartoe de
mogelijkheid heeft, en **bevestigt hij dat uitdrukkelijk aan de gebruiker**
(welke concepten, geadresseerde en onderwerp per mail), zodat de gebruiker weet
dat ze klaarstaan in Outlook. De mailtekst hoeft dan niet in het opgekuiste
ontwerp te blijven staan (het ontwerp = de akte/het document zelf). Heeft agent
2 geen Outlook-toegang, dan is dat geen blokkering: hij levert de volledige
mailtekst in zijn antwoord, of — kan hij enkel het document bewerken — in een
duidelijk gescheiden bijlage ná het ontwerp.

## Verificatiestrategie

Twee complementaire niveaus; enkel het eerste hoort in CI.

1. **Statische overdrachtsgrens-lint (in CI, goedkoop, deterministisch).** Een
   guard-test scant de teksten die letterlijk in het `.docx` worden ingebed —
   `WERKDOSSIER_AGENT_PROMPT`, `WERKBLAD_KORTE_PROMPT` en de FR-tegenhanger
   `KORTE_COPILOT_PROMPT.fr` (`lib/word/aiAgentInstructies.ts`) — op verboden
   afhankelijkheden:
   - een **denylist** van MCP-toolnamen en agent-1-only-tokens ("MCP", "sessie"
     als context-ID, "dossier-ID", "zoals besproken", de concrete toolnamen);
   - met een **allowlist** van legitieme optionele-capaciteit-formuleringen
     ("indien je webtoegang hebt", "heb je toegang tot Outlook", "ondersteunt je
     omgeving") zodat gracieuze degradatie niet vals wordt afgekeurd.
   Een nieuwe toolverwijzing die per ongeluk in de ingebedde tekst sluipt,
   faalt de test meteen. Ratchet-stijl, analoog aan `bibliotheek-audit.test.ts`.
   **→ eigen Sonnet-werf** (implementatie); dit document is de spec.

   Waarom een lint en geen inhoudsmodel: de eigenschap "de ingebedde tekst
   veronderstelt geen agent-1-context" is lexicaal en stabiel toetsbaar, draait
   in milliseconden op elke push, en heeft geen niet-determinisme of kost van
   een LLM-aanroep — precies wat een CI-poort nodig heeft.

2. **Steekproefsgewijze LLM-eval (buiten CI, duurder).** Genereer periodiek een
   `.docx` voor een realistisch dossier, geef het aan een agent-2-achtige agent
   *zonder* enige Notary.AI-toegang, en beoordeel of het resultaat (a) een
   zuiver ontwerp is met verwijderd werkblad, (b) de inhoudelijke markeringen
   behoudt, en (c) de Outlook-bevestiging geeft wanneer mails werden aangemaakt.
   Niet-deterministisch en te traag/te duur voor elke push; hoort in een aparte,
   handmatig of periodiek gedraaide evaluatie, niet in de poort.

## Bijgevoegde-stukken-manifest — architectuurbevinding (2026-07-12, Sonnet)

Opgeleverd. Bij de implementatie bleek de oorspronkelijke aanname ("afgeleid uit
de intake-/bronmetadata, `lib/dossier/intake.ts`, `Veld<T>.bron`") niet te
kloppen met de werkelijke architectuur: `app/api/dossier/word/route.ts` (de
server-side handler achter `genereerWerkdossierAlsWord`) ontvangt **nooit** een
volledig `Dossier`-object — enkel geanonimiseerde kenmerken/parameters (GDPR:
Notary.AI mag geen persoonsgegevens ontvangen). Er is dus géén
`Veld<T>.bron`-tracking beschikbaar op het moment dat het .docx wordt
samengesteld.

Het enige beschikbare signaal is het al bestaande, optionele `bron`-veld per
bevinding (`AgentBevinding.bron`, bv. "compromis p. 2", "EPC-attest") in de
`bevindingenJson` die agent 1 al meegeeft voor de tabel "Bevindingen van de
voorbereidende agent". Geïmplementeerd:
`bijgevoegdeStukkenParagrafen(bevindingen, taal)`
(`lib/word/aiAgentInstructies.ts`) herleidt daaruit een kort manifest — de
unieke, niet-lege `bron`-vermeldingen, in volgorde van eerste voorkomen — als
nieuwe sectie "Geraadpleegde brondocumenten" ná de bevindingentabel. Geen
bevindingen → geen sectie; bevindingen zonder één bron → een expliciete
leeg-melding (nooit stilzwijgend weglaten). Verankerd in
`WERKDOSSIER_AGENT_PROMPT` (OPBOUW + de docx-als-basis-verwijderlijst) en
`WERKBLAD_KORTE_PROMPT`/`KORTE_COPILOT_PROMPT.fr`.

Praktisch gevolg: de kwaliteit van dit manifest hangt volledig af van hoe
consequent agent 1 de `bron` invult per bevinding — een zwakker signaal dan de
oorspronkelijk beoogde volledige documenttracking, maar het enige dat de
GDPR-grens toelaat zonder een nieuw, apart kanaal te openen.

## Fable-restwerven — opgeleverd (2026-07-12)

- **Expliciete "geen bevindingen aangeleverd"-melding.** `bevindingenParagrafen()`
  rendert de sectie voortaan ook zónder bevindingen: geen tabel, maar de
  uitdrukkelijke melding "Geen bevindingen aangeleverd … identificeer alle
  parameters zelf vanaf nul" (NL+FR). Agent 2 leidt "vanaf nul werken" dus
  nooit impliciet uit een afwezige tabel af; `WERKDOSSIER_AGENT_PROMPT`
  (§BEVINDINGEN) benoemt het scenario nu ook met zoveel woorden.
- **Golden-path integratietest.** `genereerWerkdossierWordDocument.test.ts`
  (describe "golden path") roept de volledige generatie aan voor één
  representatief scenario en asserteert dat élke werkbladsectie verschijnt in
  de vaste volgorde (korte prompt → instructies → ontbrekende gegevens →
  structuuranker → bevindingen → stukkenmanifest → notities → mails → ontwerp
  → afrekening), plus de kale variant (geen-bevindingen-melding, geen
  stukkenmanifest/notities). Een bouwer die uit de samenstelling valt, faalt
  hier meteen.

Daarmee zijn alle werven uit dit ontwerp opgeleverd; het contract wordt blijvend
bewaakt door de guard-tests in `data/ai-prompts.test.ts`, de
overdrachtsgrens-lint in `lib/word/aiAgentInstructies.test.ts` en de
golden-path-test hierboven.
