De widget in een afgesloten omgeving
Standaard praat de widget rechtstreeks met je eigen vragen.ai-subdomein, zonder inloggegevens: iedere bezoeker mag een vraag stellen, en de rem tegen misbruik zit aan onze kant. Sommige organisaties willen dat anders. De API van hun omgeving mag alleen bereikbaar zijn met een token, zodat niemand buiten de eigen website om vragen kan stellen of kan zoeken. Dat kan. Je zet de omgeving op slot en laat de widget via een proxy op je eigen domein lopen. Die proxy voegt het token toe, en het token komt nooit in de browser.
Zo zit het in elkaar
-
In je omgeving zet je de instelling Widget op "Alleen ingelogde gebruikers en API-tokens van dit account". Die staat bij Instellingen, tabblad Beveiligingsinstellingen, in de sectie Toegang (zie het dashboard); alleen een Owner kan dit tabblad openen. Vanaf dat moment weigert je subdomein iedere aanroep van de widget zonder geldig token. Collega's die in vragen.ai zijn ingelogd, kunnen de widget wel blijven gebruiken. Het script en de opmaak van de widget zelf blijven gewoon te laden; daar zit geen kennis in.
-
Je maakt een token aan voor de proxy, onder Integraties bij de API-koppelingen. Elk API-token van je omgeving geeft toegang tot de widget, welke rechten het verder ook heeft. Geef het token daarom zo weinig rechten als kan; het staat alleen op je server.
-
Je zet een proxy op je eigen domein, bijvoorbeeld
https://www.jouwsite.nl/vragen-proxy/, die de aanroepen van de widget één op één doorzet naar je vragen.ai-subdomein en er de headerAuthorization: Bearer <token>aan toevoegt. -
In het embed-script geef je per aanroep het proxy-adres mee (zie hieronder). De widget praat dan alleen nog met je eigen domein.
Je CMS-koppelingen merken er niets van. De WordPress-plugin, de Drupal-module en een eigen API-koppeling praten al server-side met een token.
Welke aanroepen de widget doet
Alle aanroepen gaan naar je subdomein en dragen het kenmerk van je omgeving in het pad (hier [uuid]). Per aanroep staat welke parameter op het embed-script hem naar je proxy stuurt.
| Aanroep | Waarvoor | Parameter op het embed-script |
|---|---|---|
GET /agent/[uuid]/start |
Het antwoord van een agent, als stroom (Server-Sent Events) | agentEndpoint |
GET /agent/[uuid]/resume |
Het vervolg van een agentgesprek na een tussenstap | agentResumeEndpoint |
GET /agent/[uuid]/continue |
Het vervolg van een agentantwoord nadat de widget de uitkomst van een websitetool heeft teruggestuurd (alleen bij websitetools) | agentContinueEndpoint |
POST /agent/[uuid]/webmcp-tools |
De websitetools die de pagina aanbiedt (alleen bij websitetools) | webmcpToolsEndpoint |
POST /agent/[uuid]/tool-results |
De uitkomst van een websitetool (alleen bij websitetools) | toolResultsEndpoint |
GET /conversation/[uuid]/state |
Het klaarzetten van een gesprek; de widget roept dit aan vlak voordat de bezoeker een vraag stelt | stateEndpoint |
GET /conversation/[uuid]/start |
Het antwoord van een antwoordsysteem zonder agent, als stroom | answerEndpoint |
POST /conversation/[uuid]/cancel |
Het stoppen van een antwoord door de bezoeker | cancelEndpoint |
GET /conversation/[uuid]/results |
De zoekresultaten bij een vraag | searchEndpoint |
GET /conversation/[uuid]/questions |
Vraagsuggesties | questionSuggestionEndpoint |
GET /conversation/[uuid]/autocomplete |
Auto-aanvullen in je zoekveld (ook op embed-autocomplete.js) |
autocompleteEndpoint |
GET /conversation/[uuid]/facets |
De facetten voor het filterpaneel | filterFacetsEndpoint |
POST /conversation/[uuid]/feedback |
De duim omhoog of omlaag van een bezoeker, met toelichting | feedbackEndpoint |
De precieze adressen, inclusief de parameters die je deployment er soms achter zet (zoals de gekozen agent of zoekstrategie), lees je af in het script zelf. Open https://jouworganisatie.vragen.ai/embed.js?deployment=[deployment-naam] in je browser en zoek in het config-blok naar _endpoint. Neem die adressen letterlijk over en vervang alleen het domein door je proxy.
Welke aanroepen je deployment echt doet, hangt af van wat erop aanstaat. Het klaarzetten van een gesprek hoort bij elke deployment waarin bezoekers een vraag stellen. Een deployment met een agent gebruikt de agentroutes en het stoppen. De drie aanroepen voor websitetools zijn alleen nodig als je agent Websitetools (WebMCP) gebruikt: acties die je eigen website aan de agent aanbiedt, zoals een afspraak maken (zie Agents en agent mode). Verder geldt: zonder filterpaneel zijn er geen facetten en zonder zoekveld geen auto-aanvullen. Zet de parameters die bij jouw deployment horen; de rest kun je weglaten.
Het embed-script
Je geeft de proxy-adressen als extra parameters mee op de URL van het script. Het zijn volledige adressen, dus codeer ze als URL-waarde (in JavaScript: encodeURIComponent), anders breken de ? en & erin de parameterlijst. Leesbaar, vóór het coderen:
https://jouworganisatie.vragen.ai/embed.js
?deployment=[deployment-naam]
&agentEndpoint=https://www.jouwsite.nl/vragen-proxy/agent/[uuid]/start?agent=[agent-uuid]
&agentResumeEndpoint=https://www.jouwsite.nl/vragen-proxy/agent/[uuid]/resume
&stateEndpoint=https://www.jouwsite.nl/vragen-proxy/conversation/[uuid]/state
&cancelEndpoint=https://www.jouwsite.nl/vragen-proxy/conversation/[uuid]/cancel
&searchEndpoint=https://www.jouwsite.nl/vragen-proxy/conversation/[uuid]/results
&questionSuggestionEndpoint=https://www.jouwsite.nl/vragen-proxy/conversation/[uuid]/questions
&feedbackEndpoint=https://www.jouwsite.nl/vragen-proxy/conversation/[uuid]/feedback
Gecodeerd wordt dat één regel, die je als gewone scripttag op je pagina zet:
<script src="https://jouworganisatie.vragen.ai/embed.js?deployment=[deployment-naam]&agentEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fagent%2F[uuid]%2Fstart%3Fagent%3D[agent-uuid]&agentResumeEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fagent%2F[uuid]%2Fresume&stateEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fconversation%2F[uuid]%2Fstate&cancelEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fconversation%2F[uuid]%2Fcancel&searchEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fconversation%2F[uuid]%2Fresults&questionSuggestionEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fconversation%2F[uuid]%2Fquestions&feedbackEndpoint=https%3A%2F%2Fwww.jouwsite.nl%2Fvragen-proxy%2Fconversation%2F[uuid]%2Ffeedback"></script>
Laat je een parameter weg, dan gebruikt de widget voor die aanroep het gewone adres op je subdomein, en die aanroep faalt dus zodra de omgeving op slot staat. Controleer na het plaatsen in de browserconsole (F12, tabblad Netwerk) dat er geen enkele aanroep meer rechtstreeks naar je subdomein gaat, op het script en de opmaak na.
Waar je proxy op moet letten
-
Stuur door zoals het binnenkomt: methode, pad, querystring, body en
Content-Type. Zoeken en suggesties zijn gewone GET-verzoeken die JSON verwachten; feedback is een POST met JSON; het stoppen van een antwoord is een POST met formuliervelden, die de browser ook bij het sluiten van het tabblad nog verstuurt. -
Voeg alleen de header
Authorizationtoe. EenAuthorization-header die uit de browser komt, laat je niet door. -
Laat alleen de paden hierboven door, met het vaste
[uuid]van je omgeving. Zet je je hele subdomein achter de proxy, dan is je token een open doorgeefluik naar de complete API van je omgeving, kennisbank inbegrepen. -
Streaming: het antwoord komt binnen als Server-Sent Events over één verbinding die open blijft tot het antwoord af is, soms een minuut. Zet buffering uit en sta lange verbindingen toe; in nginx bijvoorbeeld
proxy_buffering off;,proxy_http_version 1.1;enproxy_read_timeout 300s;. Buffert je proxy toch, dan ziet de bezoeker niets tot het antwoord compleet is. -
Cookies: de widget stuurt cookies mee, zodat vervolgvragen en de bezoekersstatistiek bij dezelfde bezoeker horen. Geef de
Cookie-header door en laatSet-Cookieterugkomen, met het domein van je proxy. Sla je dat over, dan werkt de widget nog steeds, maar telt iedere vraag in je gesprekken als een nieuwe bezoeker. -
Eén afzender: voor ons komen al je bezoekers nu van het adres van je proxy. Meld dat via service@vragen.ai, dan stellen we de rem tegen misbruik in per omgeving in plaats van per bezoeker (zie Antwoordenlimiet en fair use). Anders raakt de proxy op een drukke dag een rem die voor één bezoeker bedoeld is.
-
Content Security Policy: script, opmaak en afbeeldingen komen nog steeds van je subdomein, de verbindingen gaan nu naar je eigen domein. Houd
script-src,style-srcenimg-srczoals in De widget op je website en zet inconnect-srcje eigen domein ('self') in plaats van je subdomein. -
Websitetools: gebruikt je agent websitetools, geef dan de headers
OriginenReferervan de browser ongewijzigd door. vragen.ai biedt de acties van een pagina alleen aan de agent aan als het verzoek van een van de "Vertrouwde websites" van die agent komt. Valt die herkomst weg, dan blijft de widget werken, maar gebruikt de agent de acties van je site niet. -
Zelfde domein: zet de proxy op het domein van de pagina waar de widget staat. Dan speelt CORS niet en blijven cookies vanzelf werken.
Wat je ermee wint
Niemand kan buiten je website om vragen stellen aan je omgeving, het token verlaat je server nooit, en al het verkeer van de widget loopt langs een punt dat jij beheert: je eigen logging, je eigen firewall, je eigen regels. De bezoeker merkt er niets van; die ziet dezelfde widget met dezelfde antwoorden.
Support
Kom je er niet uit, of wil je dat we meekijken naar je proxy-configuratie? Mail service@vragen.ai.