Voordat het model draait
De gebruiker levert een prompt en een alias zoals cheap, fast of smart. De productieserver checkt authenticatie, workspace-eigenaarschap en entitlement voordat de taak wordt geaccepteerd. Provider-model-ID's en secrets blijven achter die grens — de vriendelijke alias is de enige modelvocabulaire die de client ooit nodig heeft, omdat de mapping naar een echt providermodel configuratie is, geen contract.
Een duurzaam taakrecord geeft de request een identiteit voordat de achtergrondexecutie begint. Die identiteit verbindt de submission, de worker, usagerecords en het resultaat. Het geeft de gebruiker ook een manier om het werk te herstellen na wegnavigeren.
De volgorde doet ertoe: duur werk start pas nadat goedkope checks slagen. Authenticatie, eigenaarschap en entitlement verifiëren voordat iets in de queue gaat houdt ongeauthenticeerde of onbetaalde requests ver van een provider — en maakt de failure uitlegbaar aan de gebruiker. De AI-modulegids documenteert waar die checks leven; de workspacegrenzen-post legt uit waarom eigenaarschap op de server wordt afgeleid in plaats van van de client vertrouwd.
Bepaal wiens keys en wiens limieten
Een AI-feature is een bestedingsbeslissing. supastack laat workspaces hun eigen providerkeys meenemen — versleuteld opgeslagen, nooit aan clients blootgesteld — of op platformkeys draaien, en handhaaft budgetten per workspace tegen een modelprijscatalogus. Wat je implementatie ook is, de vragen zijn dezelfde: wie betaalt, en waar wordt de limiet afgedwongen?
Handhaving hoort in de serverworkflow, niet in een schatting aan de browserkant. Een budget dat na generatie wordt gecheckt registreert alleen overbesteding; vóór dispatch gecheckt voorkomt het die. Providerkey-setup dekt de configuratiekant.
Maak executie expliciet
Trigger.dev draait de ai.generate-workflow. De capability-aware router selecteert een model op basis van geconfigureerd beleid en de eisen van de request. Behandel dat beleid als een operationele input: een niet-beschikbare alias mag niet als werkende keuze in de interface verschijnen.
Een netwerkfout tijdens submission kan de client onzeker achterlaten over of werk in de queue is gezet. Het productiepad gebruikt een taak-scoped idempotencykey en een opgeslagen submission zodat recovery de originele request kan hergebruiken. Na elke timeout een nieuwe taak sturen zou dubbel werk en dubbele kosten riskeren.
Duurzaamheid is ook wat de interface eenvoudig houdt: het scherm leest taakstatus en rendert die in plaats van retries te orkestreren. Wanneer generatie modelcalls, toolstappen of schedules omvat, is het expliciete workflowcontract — enqueue, status, cancel — wat “in progress” eerlijk houdt.
Benoem de failure modes
Tussen request en resultaat zit een specifieke, eindige set dingen die misgaan. Ontwerp voor elk bij naam in plaats van voor “errors” in het abstract — elke taak moet eindigen in een uitlegbare state: queued, running, failed met een reden, of complete met een resultaat. Taakrecovery is de referentie van de kit voor de recoverykant.
De interface-eis eronder is dat geen state mag liegen. Een spinner die het werk overleeft, of een succesbericht voor een taak die nooit draaide, is een supportticket en een billingdispuut in wording.
- Submission liep op een timeout — herstel via de opgeslagen submission en de taak-scoped idempotencykey in plaats van opnieuw te queuen.
- Provider faalde midden in de taak — markeer de taak als gefailed met een reden die de interface kan tonen.
- Budget uitgeput — weiger vóór dispatch, niet na de besteding.
- Gebruiker navigeerde weg — het duurzame record en de recovery-URL herstellen status en resultaat.
Track wat er gebeurde
Generatie produceert meer dan tekst. De applicatie registreert gebruik en een taakresultaat, en de interface leest status via de geauthenticeerde API. Het usagerecord is wat het budget afdwingbaar maakt — het wordt geschreven voordat het resultaat terugkomt, niet achteraf geschat.
Voltooiingsmail is een aparte stap met aparte afleverrecords. Een succesvolle modelrespons stelt niet vast dat een e-mail is afgeleverd. Die uitkomsten gescheiden houden maakt failures makkelijker uit te leggen en opnieuw te proberen zonder het model onnodig opnieuw te draaien.
Het resultaat heeft ook een thuis nodig waar de gebruiker naar terug kan: een taakpagina, een historielijst, een recovery-URL die in die voltooiingsmail wordt meegeleverd. Een generatie die alleen in een vluchtige notificatie bestaat is werk dat je twee keer zult moeten leveren.
Verifieer elke grens
Gebruik deterministische fake-adapters om eerst de beslissingen van de applicatie te testen: geweigerde toegang, uitgeschakelde aliasen, dubbele submissions, resultaatrecovery en generieke fouten. Die tests moeten zonder providercredentials draaien.
Gebruik daarna het expliciet opt-in provider-smokeproces voor echte integraties. Het vereist de gedocumenteerde sandboxconfiguratie en goedkeuring om externe calls te maken. Het onderscheid houdt gewone ontwikkeling snel terwijl productiebewijs specifiek en aantoonbaar wordt.
Houd die scheiding stabiel terwijl het product verandert: deterministische dekking bij elke grensbeslissing, zodat een providerwissel, een routerbeleidswijziging of een nieuwe alias een test laat falen in plaats van een klant.
Veelgestelde vragen over AI-features in SaaS
In elk gesprek over AI achter een paywall komen een paar vragen terug.
- Waar hoort autorisatie voor AI-features te gebeuren? — Voordat iets in de queue gaat: authenticeer, resolveer de workspace, check de entitlement en maak dan pas de taak. Checks die na generatie draaien documenteren alleen misbruik.
- Heb ik bring-your-own-key-ondersteuning nodig? — Als je klanten eigen providerrelaties hebben, ja: het beslist wie betaalt en wie de ratelimieten bezit. Sla keys versleuteld op en houd ze van clients af — de AI-configuratiegids dekt het model.
- Hoe voorkom ik dat retries dubbel factureren? — Scope de idempotencykey aan de taak en hergebruik de opgeslagen submission tijdens recovery, zodat een timeout geen tweede factureerbare run kan creëren.
- Welke usagedata moet ik vastleggen? — Per taak: model, verbruikte units, kosten tegen de prijscatalogus en de workspace — genoeg om budgetten af te dwingen en bestedingsvragen te beantwoorden zonder jobs opnieuw te draaien.
- Wanneer hoort generatie in een achtergrondjob? — Wanneer het een request kan overleven. Modellatency, retries en meerstapswerk pleiten voor duurzame executie; alleen directe, goedkope calls horen inline.