“Which of our contracts carry a termination penalty?” klinkt als een taak voor een AI‑agent, en dat is het ook, maar niet door de contracten te lezen. Een agent die elk bestand opent om het te beantwoorden, verbruikt zijn context aan 297 irrelevante documenten en moet er nog op vertrouwen dat hij de clausule in de andere drie heeft opgemerkt. Met GroupDocs.Search.Mcp die lokaal in Docker draait, indexeren Claude Desktop, Cursor of Copilot de map één keer, vragen ze de index welke contracten overeenkomen, en lezen ze alleen de clausules:

Welke van mijn contracten vermelden een beëindigingsboete? Citeer de clausule voor elk contract.

Hoe stel je vragen over een map met contracten met een AI‑agent.

Wat gaat er mis wanneer de agent alles leest?

Drie dingen, in toenemende volgorde van gevaar. Het is traag en duur: elk contract gaat door het contextvenster, elke keer dat je vraagt. Het raakt vol: na een paar tientallen lange documenten vallen de eerste uit het venster of worden samengevat, en een samenvatting is waar een clausule verdwijnt. En het faalt stilletjes: “Ik heb twee contracten met een beëindigingsboete gevonden” klinkt hetzelfde of de agent alle 300 heeft gecontroleerd of slechts 40 heeft gescand. Niets in het antwoord vertelt je welke.

Een index verwijdert het eerste probleem en maakt het derde zichtbaar. De vraag “welke bestanden bevatten deze woorden” heeft een exact antwoord, en een zoektool geeft dit terug met een telwaarde die je kunt controleren.

Hoe ziet de juiste volgorde eruit?

Indexeer één keer, zoek, en lees vervolgens de overeenkomsten. Hier is wat de server teruggaf in onze test, tegen vijf synthetische contracten: twee met een boetebepaling, en één NDA die beide woorden noemt maar een boete uitsluit.

-> add_to_index {"documentsPath":"contracts","indexName":"contracts"}
<- Indexed 'contracts' into index 'contracts': 5 document(s) added,
   5 in the index.

-> search {"query":"termination penalty","indexName":"contracts"}
<- { "documentsFound": 0,
     "hint": "Unquoted words separated by spaces do not match. Search the
              phrase as \"termination penalty\", or combine the words with
              AND / OR, e.g. termination AND penalty." }

-> search {"query":"termination AND penalty","indexName":"contracts"}
<- documentsFound 3: acme-master-services-agreement.pdf,
   globex-consulting-agreement.docx, initech-nda.docx

-> get_text_fragments {"query":"\"termination penalty\"",...}
<- === contracts/acme-master-services-agreement.pdf ===
     …a termination penalty of three monthly fees applies, payable
     within 30…
   === contracts/globex-consulting-agreement.docx ===
     …Early termination penalty: the Client pays 50 percent of the fees…

Wat leren de drie resultaten ons?

De eerste query miste, en de server legde uit waarom. In GroupDocs.Search komen woorden die gescheiden zijn door spaties zonder aanhalingstekens niet overeen als een frase. In plaats van een nul terug te geven, voegt de server een hint toe die de oplossing uitlegt, en agents corrigeren zichzelf bij de volgende oproep. Dit is de meest voorkomende eerste fout, en wordt in de respons zelf afgehandeld.

AND vond drie, de frase vond twee. AND wordt per document geëvalueerd. De Initech NDA bevat beide woorden in de zin “There is no fee and no penalty associated with termination of this NDA”. Een model dat alleen het zoekresultaat leest, zou het tellen; bij het lezen van de passage meldt het de NDA apart als een contract dat de boete expliciet uitsluit. Die onderscheiding is de volledige waarde van de derde oproep.

Formaten maakten niet uit. De overeenkomsten kwamen uit een PDF en een DOCX, en een TXT‑contract zat in dezelfde index. De engine indexeert 82 formaten, dus een map die over tien jaar met verschillende tools is gegroeid, beantwoordt één query.

De oproepen, in volgorde

user              agent                         Search MCP server
 |  "Which contracts mention a termination penalty?"           |
 |---------------->|                                           |
 |                 |-- add_to_index (once) ------------------>|
 |                 |-- search {"query":"termination AND       |
 |                 |           penalty"} -------------------->|
 |                 |<- 3 files --------------------------------|
 |                 |-- get_text_fragments {"query":           |
 |                 |   "\"termination penalty\""} ----------->|
 |                 |<- the two clauses, with context ----------|
 |<- "Acme: 3 monthly fees (12.3). Globex: 50% of remaining    |
 |    fees. Initech NDA: explicitly no penalty."               |

Na de eerste indexering kost elke nieuwe vraag twee oproepen, ongeacht hoeveel contracten er zijn. “Welke contracten hebben een overmachtsclausule?” is "force majeure". “Welke huurovereenkomsten verlengen automatisch?” is renewal OR renews, en de passage zegt “verlengt automatisch voor 12 maanden tenzij een kennisgeving wordt gegeven”. Een clausule over kennisgevingsperioden is terminat? AND notice, waarbij het ? staat voor één teken en overeenkomt met terminate.

Waar de mens in de lus blijft

Dit is geen contractreview, en het mag zich niet voordoen als zodanig. De index vindt en citeert tekst; de agent vat samen wat hij geciteerd heeft. Twee gewoonten houden het eerlijk. Vraag bij elke bewering om het citaat, zodat een verkeerde samenvatting zichtbaar is naast de zin die verkeerd is gelezen. En vraag ook om de bijna‑missers, “lijst contracten die de woorden noemen zonder de clausule”, want daar is het oordeel van de lezer het belangrijkst.

Eerlijke beperkingen

  • In evaluatiemodus bevat een index maximaal 100 documenten en een zoekopdracht retourneert maximaal 10, en elke respons vermeldt dit. Roep get_license_status aan vóór een echte run, omdat een begrensd antwoord compleet lijkt.
  • Gescannde contracten zonder tekstdlaag worden alleen op basis van hun bestandseigenschappen geïndexeerd; er is geen OCR.
  • Full‑text zoeken komt overeen met woorden: een agent moet de vocabulaire van het contract gebruiken, of varianten proberen.
  • Het verwijderen van één bestand uit een geïndexeerde map wordt niet ondersteund; verwijder de map en voeg terug toe wat je wilt.

FAQ

Kan een AI‑agent al mijn contracten doorzoeken zonder ze te uploaden?
Ja. De index wordt gebouwd en doorzocht in een container op je machine; alleen de clausules die de agent citeert, bereiken het model.

Hoeveel contracten kan het aan?
Gelicenseerd, zoveel als je schijf en geheugen toelaten; de index wordt één keer gebouwd en incrementeel bijgewerkt. In evaluatiemodus stopt het bij 100 per index.

Waarom leverde mijn zoekopdracht naar twee woorden niets op?
Ongequoteerde woorden komen niet overeen als een frase. Zet ze tussen aanhalingstekens, "termination penalty", of verbind de woorden met AND; de hint van de server zegt hetzelfde.

Dieper duiken