Este tutorial constrói um agente com chamada de função onde a ferramenta exposta ao modelo nunca executa SQL arbitrário. Ele combina dois mecanismos já verificados no código Aurabase: o validador NL2SQL e uma transação Postgres somente leitura, dois blocos da IA nativaintegrados ao backend. Pré-requisitos: um projeto Aurabase, sua chave service_rolee uma conta com um dos três provedores nativos de LLM (OpenAI, Anthropic, Gemini).
O essencial
- O risco real não é a função que chama a si mesma, mas a ferramenta exposta ao modelo: um
execute_sql(query)bruto fornece acesso SQL completo. - A arquitetura segura expõe uma ferramenta
query_database(question)que delega para um validador de árvore de sintaxe (somente SELECT, LIMIT limitado, esquema isolado) em vez de execução direta. - Aurabase expõe este validador nativamente (
/nl2sql): reutilizá-lo como uma implementação da ferramenta evita ter que recodificar você mesmo a validação SQL. - O SQL confirmado é então executado por meio de
aura.db.sql()no modoreadOnly: true, uma transação real somente leitura do Postgres, não um simples filtro textual. - O endpoint
/chatnativo do Aurabase ainda não aceita uma funçãotoolnem um parâmetrotools(verificado no código): o loop do agente atualmente é executado por meio do SDK do provedor LLM, não por meio do proxy Aurabase. - A chave
service_roleignora o RLS por design: ela nunca deve sair do seu back-end e o agente herda um acesso mais amplo do que um usuário autenticado típico.
O que você vai construir
Você construirá um agente que responde a perguntas de linguagem natural sobre dados em um projeto Postgres, sem nunca deixar o modelo escrever SQL que é executado como está. O modelo chama uma ferramenta chamada query_database, esta ferramenta traduz a pergunta em SQL validado via NL2SQL, depois executa esse SQL somente leitura e retorna as linhas para o modelo para que ele formule sua resposta.
Este tutorial usa o SDK JavaScript @aurabase/aurabase-js no lado do servidor (nunca no lado do navegador, a chave service_role não deve ser exposta ao cliente) e a função OpenAI que chama a API para o loop do agente. O mesmo princípio se aplica ao SDK Anthropic ou Gemini.
Por que uma ferramenta “executar este SQL” é perigosa
A maioria dos tutoriais do agente Postgres, incluindo alguns guias oficiais, definem uma única ferramenta: uma função execute_sql que recebe uma string SQL como argumento e a executa como está. O próprio modelo escreve essa string, com base na pergunta do usuário e no esquema fornecido a ele no contexto.
Esta escolha transfere para o modelo uma responsabilidade que este não pode cumprir de forma confiável. Uma injeção imediata inserida na questão pode produzir SQL destrutivo que a ferramenta executa indiscriminadamente, uma vez que não tem noção de como deveria ser uma consulta "legítima". Nosso artigo dedicado detalha este vetor de ataque: protegendo NL2SQL contra injeção de SQL.
A alternativa criada neste tutorial expõe uma ferramenta mais restrita, query_database(question). O modelo não pode mais escrever SQL diretamente: ele só pode fazer uma pergunta em sua própria chamada de ferramenta. É o motor Aurabase NL2SQL que traduz esta questão em SQL, antes de passá-la através de um validador de árvore sintática (SELECT sozinho, sem subconsultas, dez funções autorizadas, LIMIT limitado).
Uma ferramenta execute_sql(query: string) fornece ao modelo acesso SQL completo, independentemente da qualidade do prompt do sistema. Uma instrução ("executa apenas SELECTs") continua sendo uma instrução que o modelo pode seguir, interpretar mal ou ser contornada por uma injeção inserida na pergunta do usuário.
Defina o esquema da ferramenta exposta ao modelo
Os três provedores LLM nativos da Aurabase (OpenAI, Anthropic, Gemini) aceitam uma tabela de definições de ferramentas no formato JSON Schema. Para este agente basta uma única ferramenta: query_database, que responde uma pergunta em linguagem natural e nada mais. O modelo não vê o esquema SQL nem um campo query que ele mesmo possa preencher.
Implemente a ferramenta: NL2SQL então somente leitura
O manipulador de ferramentas é executado em seu back-end, nunca no navegador. Ele carrega a chave do projeto service_role, que ignora o RLS por design e, portanto, nunca deve ser exposta a um cliente. Faz duas chamadas para o SDK Aurabase.
A primeira chamada traduz a pergunta em SQL validado via aura.ai.nl2sql(): somente SELECT, LIMIT limitado, sem acesso ao catálogo do sistema. O segundo executa esse SQL já validado via aura.db.sql(), com a opção readOnly: true: o próprio Postgres então recusa qualquer escrita nesta transação, independente da validação textual já aplicada pelo upstream do NL2SQL.
readOnly: true aciona uma transação Postgres real somente leitura: o mecanismo recusa a gravação, não é um filtro aplicado ao texto da solicitação. Combinado com a validação somente SELECT do NL2SQL, o agente possui duas camadas independentes: se uma tiver uma falha, a outra ainda será válida.
O loop do agente: chamada de função no SDK do fornecedor
Aurabase expõe três provedores LLM nativos, mas seu endpoint /chat ainda não retransmite um parâmetro tools ou função tool. ChatOptions carrega apenas temperature, max_tokens e model, e as funções aceitas são limitadas a system, user e assistant (verificadas em llm/mod.rs e handlers/chat.rs). O loop de chamada de função, portanto, é executado hoje diretamente através do SDK do provedor, não através do proxy Aurabase.
Contanto que o Aurabase não orquestre nativamente as chamadas de ferramentas, seu back-end deve gerenciar o próprio loop com o SDK OpenAI, Anthropic ou Gemini. A execução de NL2SQL e SQL permanecem chamadas clássicas do Aurabase dentro deste loop.
O princípio permanece o mesmo se você orquestrar o agente com LangChain ou um serviço como o Azure AI Agent: a ferramenta declarada na estrutura deve permanecer a mesma query_database, nunca um executor SQL bruto. Nossa comparação detalha onde LangChain e LlamaIndex fornecem valor real no Postgres e onde eles adicionam complexidade especialmente: Agentes Postgres com LangChain ou LlamaIndex.
Teste com uma pergunta real
Pergunta enviada ao agente: “Quantos clientes premium fizeram um pedido este mês?” ". O modelo chama query_database com esta pergunta como está, sem nunca ver ou escrever nenhum SQL. Aqui está o resultado das duas chamadas internas acionadas pela ferramenta.
A resposta final do modelo é baseada nessas linhas reais, não em uma suposição. Se a ferramenta retornar zero linhas, uma alucinação numérica se tornará significativamente menos provável do que com um modelo que responderia sem dados verificados.
Proteja o agente antes de entrar em produção
- A chave
service_rolenunca sai do seu backend: nem no prompt enviado ao modelo, nem em um log, nem em uma variável de ambiente do lado do cliente. readOnly: truepermanece ativo emaura.db.sql()para esta ferramenta específica, mesmo se seu projeto precisar ser escrito em outro lugar no aplicativo.service_roleignora RLS por design. Se o agente responder de forma diferente dependendo do usuário que faz a pergunta, filtre explicitamente no SQL ou volte para os endpoints PostgREST clássicos, que respeitam o RLS. Consulte isolamento RLS multilocatário.- Registrar cada chamada de ferramenta (pergunta feita, SQL validada, número de linhas): este é o único rastreamento utilizável se uma pergunta produzir um resultado inesperado.
- A limitação de taxa e a cota mensal do Aurabase já se aplicam por projeto em
/nl2sql: um agente falante não pode exceder silenciosamente seu orçamento de IA.
Limites atuais a serem observados
A ferramenta query_database herda todas as limitações do validador NL2SQL: sem subconsultas, sem CTE/WITH, sem UNION e uma lista fechada de dez funções SQL. Uma questão que naturalmente exige uma subconsulta (“clientes que nunca fizeram pedidos”) deve ser reformulada ou processada por uma segunda ferramenta dedicada, em vez de forçada ao NL2SQL.
Nenhuma orquestração de chamadas de ferramenta existe hoje dentro do proxy Aurabase /chat: o loop do agente descrito aqui reside no código do seu aplicativo, não em um serviço gerenciado. Se o agente precisar encadear diversas ferramentas (banco de dados e RAG documental, por exemplo), é o seu backend que orquestra as duas chamadas.
RAG e chamada de função combinadas
Este tutorial cobre questões estruturadas sobre dados relacionais. Para dúvidas sobre conteúdos não estruturados (documentos, tickets, notas), o mesmo agente pode expor uma segunda ferramenta conectada ao RAG nativo do Aurabase (pgvector, busca HNSW). As duas capacidades e sua articulação estão detalhadas na página Native AI on Postgres.