Het meeste SaaS-werk dat op ons bureau belandt is Laravel. Al jaren. Wat in 2026 veranderde: "een AI-feature toevoegen" werd een uitgemaakte zaak in plaats van een onderzoeksproject. Laravel 13 kwam uit op 17 maart 2026, en daarnaast landde de eigen AI SDK van het framework — laravel/ai, uitgebracht op 5 februari 2026 — als first-party manier om met LLM-providers te praten. De demo is een controller van vijf regels. De productiebuild is alles eromheen.

Niets van wat volgt is exotisch. Het is de saaie steigers die een bureau hergebruikt zodat de derde AI-feature een fractie kost van de eerste, en zodat het ops-team van de klant kan slapen. Verkoop je Laravel-software, dan is dit de checklist die wij aflopen.

Eerst: kies de laag, niet de provider

Vóór alle patronen één beslissing. Hoe bereikt je code eigenlijk een model?

  • Laravel AI SDK (laravel/ai) — het officiële pakket. De kernbouwsteen is de Agent: een aparte PHP-class met de instructies, gesprekscontext, tools en output-schema voor één taak. Het doet streaming, gestructureerde output, embeddings, beeld en audio, en levert test-fakes. Voor een nieuwe Laravel 13-build is dit onze standaard.
  • Prism (prism-php/prism) — het community-pakket dat er als eerste was en nog steeds uitstekend is. Zelfde idee: één vloeiende interface over OpenAI, Anthropic, Mistral, Gemini en lokale Ollama-modellen, met schema-gevalideerde output en tool calling. Gebruikt een app het al, dan houden we het.
  • Rauwe HTTP naar een provider — alleen als we iets nodig hebben dat geen van beide pakketten al blootlegt. Een prima noodluik, nooit het startpunt.

De twee pakketten liggen dicht genoeg bij elkaar dat de keuze niet dragend is: allebei geven je één interface over providers, dus later het model — of het hele pakket — wisselen is goedkoop. Wat telt is dat er iets tussen je app en de leverancier zit. En dat is het eerste patroon.

Patroon 1 — de modelcall zit achter een interface

Geen enkele controller belt rechtstreeks een provider. Nooit. Elke modelinteractie zit achter een applicatieservice — een Agent-class in de SDK, of je eigen interface om Prism heen — met een methode die je domein spreekt: summariseTicket(), draftReply(), classifyDocument(). De controller roept dát aan. Hij heeft geen idee welk model antwoordde.

Dat levert drie dingen op die je nodig gaat hebben. Je kunt Claude inruilen voor Mistral omdat de data van de klant de EU niet uit mag, en je raakt één class aan. Je kunt de hele AI-laag mocken in een test. En je krijgt één plek voor de logging, retries en kostentracking waar patroon 5 en 6 op leunen. Een provider-SDK-call uitgesmeerd over twaalf controllers is een refactor die je twee keer betaalt.

Het model is een dependency, geen feature. Behandel het als je database-driver: uitwisselbaar, ingepakt, en nooit direct vanuit een controller aangeroepen.

Patroon 2 — alles wat een model aanroept draait op een eigen queue

Modelcalls zijn traag, geheugenhongerig, grillig en foutgevoelig op manieren die je gewone jobs niet zijn. Eén completion kan tientallen seconden stilstaan vóór het eerste token. Zet dat op de standaard-queue en één sloom provider-antwoord houdt je welkomstmails en je facturatie-webhooks op.

Dus AI-werk krijgt een eigen queue en eigen workers. Concreet: een aparte ai-connectie, een eigen Horizon-supervisor, en een timeout ruim boven de standaard 60 seconden van Horizon, want die standaard schiet een call met veel context halverwege dood. Redis als driver. Retries met exponentiële backoff voor de onvermijdelijke 429's en 503's van de provider. En jobs die idempotent zijn, want een herhaalde job die een klant dubbel afrekent of twee keer antwoordt is erger dan een mislukking. Het punt is simpel: AI-belasting moet kunnen pieken, hangen en falen zonder de rest van de app te raken.

Patroon 3 — stream naar de gebruiker, bewaar in de job

Gebruikers verwachten inmiddels het token-voor-token typegevoel; een spinner van vijftien seconden voelt als kapot. Maar op het moment dat je gaat streamen heb je een duurzaamheidsprobleem — een stream die een page-refresh weggooit is geen opgeslagen gesprek.

We splitsen het in twee lagen, en dit is het patroon dat de meeste eerste pogingen fout doen. De live stream is een aparte HTTP-request over SSE — de stream() van de SDK geeft een respons met de juiste text/event-stream-headers en duwt tokens door zodra ze binnenkomen. De duurzame kopie schrijft de queued job uit patroon 2, die de volledige completion verzamelt en in de database opslaat. Streamen voor het gevoel; opslaan voor de waarheid. Valt de verbinding weg, dan laad je uit de database, niet uit een stream die al weg is. Geen WebSocket-server nodig.

Patroon 4 — gestructureerde output, gevalideerd, of het faalt luid

De snelste weg naar een broze AI-feature is json_decode() op een ruwe modelstring en een beetje hopen. Modellen driften, pakken JSON in proza in en verzinnen velden. Parse dat met de hand en je levert een bug die alleen opduikt bij de output die je niet testte.

Dus we vragen nooit om "wat JSON". We definiëren een schema en gebruiken gestructureerde output. Zowel de AI SDK als Prism onderhandelen dat schema met de provider en valideren de respons daartegen — en, cruciaal, ze gooien een fout als het model iets teruggeeft dat niet past, in plaats van je stilletjes kapotte data te geven. Een validatiefout die je kunt vangen, loggen en opnieuw proberen is beter dan een null die drie lagen verderop opduikt als een gebroken factuur. Combineer het met de backoff uit patroon 2 en de foutmodus wordt "retry, dan alarm", niet "record corrupt".

Patroon 5 — log elke prompt, token en euro

De tokenrekening is zelden de grootste kostenpost van een AI-feature, maar wel de post die klanten verrast — en de post die je zonder data niet kunt uitleggen. Dus elke call door de service-laag schrijft een regel weg: welke agent, welk model, prompt- en completion-tokens, latency, kosten, en de gebruiker of tenant waar het bij hoorde.

Die ene tabel verdient zich op vier manieren terug. Je beantwoordt "waarom kostte vorige maand het dubbele" in één query. Je factureert eerlijk per tenant op een SaaS. Je spot de op hol geslagen prompt die na een "kleine" wijziging stilletjes verdrievoudigde. En als de reviewer van een EU-klant vraagt hoe het systeem beslissingen neemt, heb je het audittrail al liggen — dezelfde logging die de transparantieplichten van de AI Act verwachten, ingebouwd vanaf dag één in plaats van erin gefrommeld de week vóór livegang. Omdat de service-laag het ene knelpunt is (patroon 1), is dit een paar regels in een decorator, niet een wijziging op twaalf plekken.

Patroon 6 — een nep-provider in elke test

Een testsuite die bij elke run een echt model raakt is traag, flaky, niet-deterministisch en — omdat de modelprijzen van 2026 per token gaan — stilletjes duur. Dus de standaard in elke test is een gefakete provider. De AI SDK levert fakes: je assert dat een agent is aangeroepen met de prompt die je verwacht en geeft een canned response terug, precies zoals Http::fake() werkt voor HTTP-calls. De suite blijft snel, deterministisch en gratis.

Dat betekent niet dat je nooit een echt model raakt. We houden een kleine, aparte set live-provider-tests achter een flag, voor de handvol paden waar de echte modeloutput hét is wat je test — de accuraatheid van een classifier, de neiging van een prompt om te weigeren. Die draaien op een schema in CI, niet bij elke push. De vuistregel: fake het leidingwerk, steekproef de intelligentie.

Nog even over de EU

Twee van deze patronen zijn in Europa niet alleen hygiëne — ze zijn hefboom. De interface (patroon 1) is wat je toelaat een klant zonder herschrijving van een Amerikaanse provider naar een EU-gehoste te verplaatsen zodra dataresidentie ter sprake komt. De logging (patroon 5) is een vliegende start op de transparantie- en PII-vragen die een functionaris gegevensbescherming je stelt. Die vragen lopen we in detail langs in de AVG-checklist voor AI-features; de kern hier is dat de architectuur die je SaaS onderhoudbaar houdt dezelfde is die hem compliant houdt. Dat is geen toeval om te verspillen.

De bonus tijdens het bouwen: Boost

Nog één stuk, en het gaat over hóe je de code schrijft, niet over wat er in productie draait. Laravel Boost is de officiële MCP-server van het framework-team voor AI-ondersteund ontwikkelen. Het geeft je codeerassistent échte context over de app die hij bewerkt — je Laravel- en PHP-versies, geïnstalleerde packages, database-schema, routes, Artisan-commando's — plus een documentatie-API met duizenden Laravel-specifieke antwoorden. Het is een versneller tijdens het bouwen, geen runtime-dependency, en het maakt AI-geschreven Laravel-code merkbaar minder fout. Tien minuten installeren waard op elke serieuze build.

FAQ

Laravel AI SDK of Prism — wat kun je het beste gebruiken?

Voor een nieuwe build op Laravel 13 begin je met de officiële Laravel AI SDK: first-party, testbaar, en de Agent-classes passen naadloos op ons service-laag-patroon. Prism is het volwassen community-pakket dat er als eerste was en nog steeds uitstekend is — daar grijp je naar als een bestaande app het al gebruikt, of als je een feature nodig hebt die de SDK nog niet heeft. Beide geven je één interface over OpenAI, Anthropic en anderen, dus de migratiekosten tussen de twee zijn laag.

Waarom zet je AI-calls op een eigen queue in plaats van de standaard?

Modelcalls zijn traag, geheugenhongerig, grillig en foutgevoelig op manieren die je gewone jobs niet zijn. Meng je ze in de standaard-queue, dan houdt één trage provider-respons je wachtwoord-reset-mails op. Geef AI-werk een eigen queue en eigen workers, zet de timeout boven de standaard 60 seconden, en je kunt het los van de rest van de app opschalen en laten falen.

Hoe stream je een modelrespons naar de gebruiker maar bewaar je hem ook bij een refresh?

Behandel het als twee lagen. De live token-stream is een aparte HTTP-request over Server-Sent Events voor het directe gevoel; de duurzame kopie schrijft een queued job die de volledige completion in de database opslaat. Valt de verbinding weg of ververst de gebruiker, dan laad je uit de database, niet uit een stream die al weg is.

Hoe voorkom je dat een model kapotte JSON teruggeeft?

Gebruik gestructureerde output met een schema. Zowel de Laravel AI SDK als Prism onderhandelen een schema met de provider en valideren de respons daartegen, en gooien een fout als het model iets teruggeeft dat niet past in plaats van je rommel te geven. Je wikkelt de call nog steeds in een retry met backoff, maar je parseert nooit een ruwe string en hoopt er het beste van.

Hoe test je AI-features zonder bij elke run een betaalde API te bellen?

Fake de provider. De Laravel AI SDK levert fakes zodat je kunt asserten dat een agent met de juiste prompt is aangeroepen en canned responses teruggeeft, net zoals Http::fake() werkt voor HTTP. Je testsuite blijft snel, deterministisch en gratis, en je houdt een kleine, aparte set echte-provider-tests achter een flag voor de paden waar de echte modeloutput er wél toe doet.

Bronnen: Laravel, Laravel AI SDK en Laravel Boost · Laravel News, Laravel announces official AI SDK en what we know about Laravel 13 · Prism, prismphp.com en structured output docs. Package-API's bewegen snel — check de actuele docs voordat je een versie vastlegt.

Een AI-feature scopen op een bestaande Laravel-app en wil je een tweede paar ogen op de architectuur? Plan een call — we helpen je het bedraden, white-label.