In deze zelfstudie wordt een agent gebouwd met functieaanroepen waarbij de tool die aan het model wordt blootgesteld nooit willekeurige SQL uitvoert. Het combineert twee mechanismen die al zijn geverifieerd in de Aurabase-code: de NL2SQL-validator en een alleen-lezen Postgres-transactie, twee bouwstenen van denative AI geïntegreerd in debackend. Vereisten: een Aurabase-project, de service_role-sleutel en een account bij een van de drie native LLM-providers (OpenAI, Anthropic, Gemini).
De essentie
- Het echte risico is niet de functie die zichzelf aanroept, maar de tool die aan het model wordt blootgesteld: een onbewerkte
execute_sql(query)geeft het volledige SQL-toegang. - De veilige architectuur beschikt over een
query_database(question)-tool die delegeert aan een syntaxisboomvalidator (alleen SELECT, begrensd LIMIT, geïsoleerd schema) in plaats van directe uitvoering. - Aurabase stelt deze validator native beschikbaar (
/nl2sql): door deze te hergebruiken als een implementatie van de tool vermijdt u dat u de SQL-validatie zelf opnieuw hoeft te coderen. - De vastgelegde SQL wordt vervolgens uitgevoerd via
aura.db.sql()in dereadOnly: true-modus, een daadwerkelijke alleen-lezen Postgres-transactie, en niet een eenvoudig tekstueel filter. - Het oorspronkelijke
/chat-eindpunt van Aurabase accepteert nog geentool-rol, noch eentools-parameter (geverifieerd in de code): de agentlus loopt momenteel via de SDK van de LLM-provider, niet via de Aurabase-proxy. - De sleutel
service_roleomzeilt RLS door zijn ontwerp: hij mag uw backend nooit verlaten en de agent erft bredere toegang dan een typische geverifieerde gebruiker.
Wat je gaat bouwen
U bouwt een agent die vragen in natuurlijke taal over gegevens in een Postgres-project beantwoordt, zonder het model ooit SQL te laten schrijven die wordt uitgevoerd zoals het is. Het model roept een tool aan genaamd query_database, deze tool vertaalt de vraag naar SQL gevalideerd via NL2SQL, voert vervolgens deze alleen-lezen SQL uit en stuurt de regels terug naar het model zodat het zijn antwoord formuleert.
Deze tutorial gebruikt de @aurabase/aurabase-js JavaScript SDK aan de serverzijde (nooit aan de browserzijde, de service_role sleutel mag niet zichtbaar zijn voor de client) en de OpenAI-functieaanroep-API voor de agentlus. Hetzelfde principe is van toepassing op de Anthropic of Gemini SDK.
Waarom een “run this SQL”-tool gevaarlijk is
De meeste tutorials voor agenten van Postgres, inclusief enkele officiële handleidingen, definiëren één enkele tool: een execute_sql-functie die een SQL-tekenreeks als argument neemt en deze uitvoert zoals hij is. Het model schrijft deze string zelf, op basis van de vraag van de gebruiker en het schema dat eraan wordt gegeven in de context.
Deze keuze draagt een verantwoordelijkheid over aan het model die het niet op betrouwbare wijze kan vervullen. Een promptinjectie in de vraag kan destructieve SQL opleveren die de tool zonder onderscheid uitvoert, omdat deze geen idee heeft hoe een 'legitieme' query eruit zou moeten zien. Ons speciale artikel beschrijft deze aanvalsvector: NL2SQL beveiligen tegen SQL-injectie.
Het alternatief dat in deze tutorial is ingebouwd, maakt gebruik van een smallere tool, query_database(question). Het model kan niet langer rechtstreeks SQL schrijven: het kan alleen een vraag stellen in zijn eigen tool call. Het is de Aurabase NL2SQL-engine die deze vraag in SQL vertaalt, voordat deze door een syntactische boomvalidator wordt geleid (alleen SELECT, geen subquery's, tien geautoriseerde functies, beperkte LIMIT).
Een execute_sql(query: string)-tool geeft het model volledige SQL-toegang, ongeacht hoe goed uw systeemprompt is. Een instructie ("voert alleen SELECT's uit") blijft een instructie die het model kan volgen, verkeerd interpreteren of omzeild kan zien door een injectie in de vraag van de gebruiker.
Definieer het schema van de tool die aan het model wordt blootgesteld
De drie native LLM-providers van Aurabase (OpenAI, Anthropic, Gemini) accepteren een tabel met tooldefinities in JSON Schema-indeling. Eén enkele tool is voldoende voor deze agent: query_database, waarmee een vraag in natuurlijke taal kan worden gesteld en niets anders. Het model ziet noch het SQL-schema, noch een query-veld dat het zelf zou kunnen invullen.
Implementeer de tool: NL2SQL en daarna alleen-lezen
De toolhandler draait op uw backend, nooit in de browser. Het bevat de projectsleutel service_role, die RLS door het ontwerp omzeilt en daarom nooit aan een client mag worden blootgesteld. Er worden twee oproepen gedaan naar de Aurabase SDK.
De eerste aanroep vertaalt de vraag in SQL, gevalideerd via aura.ai.nl2sql(): alleen SELECT, LIMIT beperkt, geen toegang tot de systeemcatalogus. De tweede voert deze SQL uit die al is gevalideerd via aura.db.sql(), met de optie readOnly: true: Postgres weigert vervolgens zelf elk schrijven in deze transactie, onafhankelijk van de tekstuele validatie die NL2SQL upstream al heeft toegepast.
readOnly: true activeert een echte alleen-lezen Postgres-transactie: de engine weigert het schrijven, het is geen filter dat op de verzoektekst wordt toegepast. Gecombineerd met de SELECT-only-validatie van NL2SQL heeft de agent twee onafhankelijke lagen: als er in de ene een fout zit, blijft de andere dat ook doen.
De agentlus: functie die de SDK-kant van de leverancier aanroept
Aurabase stelt drie native LLM-providers beschikbaar, maar het /chat-eindpunt geeft nog geen tools-parameter of tool-rol door. ChatOptions bevat alleen temperature, max_tokens en model, en geaccepteerde rollen zijn beperkt tot system, user en assistant (geverifieerd in llm/mod.rs en handlers/chat.rs). De functieaanroepende lus loopt daarom vandaag rechtstreeks via de SDK van de provider, niet via de Aurabase-proxy.
Zolang Aurabase niet native tooloproepen orkestreert, moet uw backend de lus zelf beheren met de OpenAI, Anthropic of Gemini SDK. NL2SQL- en SQL-uitvoering blijven klassieke Aurabase-aanroepen binnen deze lus.
Het principe blijft hetzelfde als u de agent orkestreert met LangChain of een service zoals Azure AI Agent: de tool die in het raamwerk is gedeclareerd, moet dezelfde query_databaseblijven, nooit een onbewerkte SQL-uitvoerder. Onze vergelijkingsdetails laten zien waar LangChain en LlamaIndex echte waarde bieden op Postgres, en waar ze vooral complexiteit toevoegen: Postgres-agents met LangChain of LlamaIndex.
Test met een echte vraag
Vraag verzonden naar agent: “Hoeveel premiumklanten hebben deze maand een bestelling geplaatst?” ". De sjabloon roept query_database aan met deze vraag zoals deze is, zonder ooit een SQL te zien of te schrijven. Hier is het resultaat van de twee interne oproepen die door de tool zijn geactiveerd.
Het uiteindelijke antwoord van het model is gebaseerd op deze werkelijke lijnen, en niet op een gok. Als de tool nul rijen retourneert, wordt een getallenhallucinatie aanzienlijk minder waarschijnlijk dan bij een model dat zou reageren zonder geverifieerde gegevens.
Beveilig de agent voordat deze in productie gaat
- De sleutel
service_roleverlaat nooit uw backend: noch in de prompt die naar het model wordt verzonden, noch in een logbestand, noch in een omgevingsvariabele aan de clientzijde. readOnly: trueblijft actief opaura.db.sql()voor deze specifieke tool, zelfs als uw project elders in de applicatie moet worden geschreven.service_roleomzeilt RLS door zijn ontwerp. Als de agent anders moet reageren, afhankelijk van de gebruiker die de vraag stelt, filter dan expliciet de SQL in of val terug op klassieke PostgREST-eindpunten, die RLS respecteren. Zie RLS-isolatie voor meerdere tenants.- Registreer elke tooloproep (stelde vraag, SQL gevalideerd, aantal regels): dit is de enige bruikbare tracering als een vraag een onverwacht resultaat oplevert.
- De tarieflimiet en het maandelijkse quotum van Aurabase gelden al per project op
/nl2sql: een spraakzame agent kan niet stilletjes uw AI-budget overschrijden.
Huidige limieten waar u rekening mee moet houden
De tool query_database erft alle beperkingen van de NL2SQL-validator: geen subquery's, geen CTE/WITH, geen UNION en een gesloten lijst van tien SQL-functies. Een vraag die uiteraard om een subquery vraagt (“klanten die nog nooit besteld hebben”) moet opnieuw geformuleerd worden, of verwerkt worden door een tweede speciale tool, in plaats van in NL2SQL geforceerd te worden.
Er bestaat momenteel geen orkestratie van tooloproepen binnen de Aurabase /chat proxy: de hier beschreven agentlus bevindt zich in uw applicatiecode, niet in een beheerde service. Als de agent meerdere tools aan elkaar moet koppelen (bijvoorbeeld database en documentaire RAG), is het uw backend die de twee oproepen orkestreert.
RAG en functieaanroepen gecombineerd
Deze tutorial behandelt gestructureerde vragen over relationele gegevens. Voor vragen over ongestructureerde inhoud (documenten, tickets, notities) kan dezelfde agent een tweede tool beschikbaar stellen die is verbonden met de native RAG van Aurabase (pgvector, HNSW search). De twee mogelijkheden en hun articulatie worden gedetailleerd beschreven op de pagina Native AI op Postgres.