Naar de inhoud
hans
Werk Expertise Diensten CV Portfolio Koppelingen Laravel packages Blog Aanmelden Contact opnemen

Een assistent die in je applicatie mag

Het interessante aan een assistent is niet dat hij tekst schrijft, maar dat hij iets kan doen in een systeem dat van jou is. Daarvoor heeft hij een deur nodig, en die deur bepaal jij: wat erdoor mag, met welke sleutel, en waar het stopt.

Wat MCP is

MCP staat voor Model Context Protocol: een afspraak over hoe een assistent gereedschap van buiten leert kennen en gebruiken. Je server zegt welke handelingen er zijn, welke gegevens elk ervan verwacht en wat ze teruggeeft; de assistent kiest op basis daarvan wat hij oproept. Het verschil met een gewone api is dat het protocol gemaakt is om beschreven te worden: de assistent leest de beschrijving en hoeft niet vooraf geprogrammeerd te zijn voor jouw systeem.

Praktisch betekent dat: bouw je het een keer, dan werkt het met elke assistent die het protocol spreekt, in plaats van dat je per aanbieder iets anders moet maken. En het betekent dat je oude rest-api er niet uit hoeft. In dit project liggen ze naast elkaar en lopen ze allebei door dezelfde code, zodat er niet stilletjes twee versies van dezelfde regels ontstaan.

Wat ik erop gebouwd heb

Zes stukken tussen een assistent en een applicatie die van jou blijft.

Een MCP-server op de eigen applicatie

Deze site heeft er een: een assistent kan er de blog mee lezen en beschrijven, en een artikel aanleveren. MCP is het protocol waarmee een assistent gereedschap van buiten leert kennen, en het scheelt je een eigen koppeling per assistent.

Dezelfde handeling langs drie kanalen

Een artikel kan binnenkomen via het formulier in de admin, via de rest-api of via de MCP-server. Alle drie lopen ze langs dezelfde schrijver in de code, zodat er een set regels is en niet drie die langzaam uit elkaar groeien.

Een sleutel per assistent, niet per persoon

Elke assistent krijgt zijn eigen sleutel, aangemaakt in de admin en enkel op dat ene moment zichtbaar. In de databank staat een sha256-afdruk, dus wie de tabel leest heeft nog niets. Intrekken is een knop.

Rechten die het verzoek overrulen

Een sleutel zonder het recht om te publiceren krijgt niets online, wat er ook in het verzoek staat. Wat binnenkomt blijft een concept tot een mens het nakijkt. De grens zit in de sleutel en niet in de belofte van de assistent.

Een tekstversie van elke pagina

Naast llms.txt, dat de site samenvat, heeft elke publieke pagina een .md-variant op dezelfde url met .md erachter. Die wordt uit dezelfde html afgeleid, dus de tekstversie kan niet uit de pas lopen met wat een bezoeker ziet.

Een helpdesk die een assistent kan bedienen

Voor FreeScout schreef ik een MCP-server, zodat een assistent gesprekken kan opzoeken en beantwoorden binnen de grenzen die de sleutel toelaat, in plaats van iemand te laten knippen en plakken uit een scherm.

Hoe het in elkaar zit

Vijf regels die bepalen of je dit rustig kan laten draaien of dat je er elke dag naar moet kijken.

Behandel een assistent als een externe partij

Niet als een collega met een account, en niet als een stuk van je eigen code. Een eigen sleutel, eigen rechten, een eigen rem op het aantal verzoeken, en een logboek van wat ze deed. Dat is precies wat je bij een koppeling met een andere onderneming ook zou doen, en om dezelfde redenen.

Wat binnenkomt is een voorstel, geen feit

Een assistent die rechtstreeks publiceert, mailt of factureert, is een assistent die op een slechte dag rechtstreeks een fout publiceert, mailt of factureert. Zet er een staat tussen: concept, wachtrij, ter goedkeuring. Dat kost een klik en het scheelt de dag waarop het misgaat.

Een api is geen scherm

Wat een mens uit een scherm afleidt, moet voor een assistent expliciet in het antwoord staan: welke velden er zijn, wat verplicht is, wat een fout betekent en wat de volgende stap is. Een api die dat niet zegt, laat de assistent gokken, en gokken ziet er in tekst uit als zekerheid.

Een rem hoort erbij

Een assistent die in een lus belandt, stuurt honderden verzoeken voor iemand het merkt. Een teller per sleutel, een duidelijke 429 en een antwoord dat zegt hoe lang wachten volstaat om dat een ongemak te laten zijn in plaats van een storing.

De tekst die je aanlevert is invoer, geen instructie

Wat uit een model komt, of wat een bezoeker in een veld typte dat door een model gelezen wordt, is gegeven. Het hoort nooit te bepalen wat je applicatie doet. Die grens trek je in de code, en niet in de formulering van de opdracht.

Wat het niet is

Dit gaat niet over een chatvenster op je website. Dat is een ander soort project, met andere risico's, en het is doorgaans niet waar de winst zit. De winst zit bij het werk dat nu met knippen en plakken tussen twee schermen gebeurt: een samenvatting die iemand overtikt, een ticket dat iemand overzet, een tekst die iemand ergens anders opnieuw invoert.

En het gaat niet over de assistent vertrouwen. De hele opzet is er net op gericht dat je dat niet hoeft: de grens zit in de sleutel, in de rechten en in de staat waarin het werk binnenkomt. Werkt de assistent goed, dan scheelt dat tijd. Werkt hij een keer niet goed, dan staat er een concept dat je weggooit.

Wil je zo een deur op je eigen systeem

Meestal begint dat met een vraag die niets met AI te maken heeft: welke handelingen in jouw applicatie zijn het waard om van buitenaf te kunnen oproepen. Is dat duidelijk, dan is de rest bouwwerk. Stuur gerust een bericht.

De documentatie van de api van deze site staat op llms.txt, en wie er aan de sleutelkant over wil nadenken vindt dat bij identiteit en toegang.