Home Banco de dados Agentes por API Automações Guia do Harness Falar no WhatsApp
Bancos de dados

O banco da sua empresa dentro do site

A planilha exportada envelhece no dia seguinte. O banco que roda no sistema da loja ou no ERP do escritório ninguém quer abrir para a internet. A FlexPage liga o site a esse banco — o Harness lê a estrutura, monta a consulta e mostra o SQL antes de rodar, e o app publicado usa a mesma conexão, guardada cifrada no painel.

Credencial cifrada, nunca no código Usuário só-leitura recomendado Consulta com prazo e limite de linhas
Quatro caminhos

Escolha por onde o site chega ao seu banco

Dá para ligar o banco direto no painel, por um conector MCP, pela rede privada da empresa — ou não usar banco nenhum, guardando os registros em arquivo no próprio site.

🗄️ Bancos de dados

Conexão direta pelo painel

Para o MySQL da hospedagem, o PostgreSQL do servidor, o Supabase, o Aurora. Em 🔌 Conectores, na parte 🗄️ Bancos de dados, o botão ➕ Nova conexão abre o formulário completo:

  • Nome exibido e Identificador (ex.: agenda)
  • Banco — ao escolher, aparece a porta padrão e uma dica de onde achar o host
  • Host, Porta, Usuário, Senha e Banco (database), com a Criptografia em Exigir
  • Em quais sites a conexão pode ser usada — nenhum marcado = todos
  • ⚡ Testar conexão responde algo como “Conectado em 180 ms · 3 tabela(s): servicos, barbeiros, agendamentos”; depois, 💾 Salvar conexão

Nas sessões do Harness a conexão aparece como fonte externa e rende duas ferramentas: db_schema, que mostra tabelas e colunas, e db_query, que roda o SELECT.

🔌 Conector MCP

Supabase e MongoDB Atlas

Os dois bancos que já oferecem um servidor MCP remoto aparecem como modelo pronto em 🔌 Conectores → ➕ Novo conector:

  • Supabase: URL https://mcp.supabase.com/mcp?project_ref=SEU_PROJECT_ID&read_only=true e o cabeçalho Authorization com Bearer sbp_…. O project_ref prende o conector a um projeto; read_only=true faz o banco recusar alterações.
  • MongoDB Atlas: usa Client ID e Client Secret de uma MCP configuration — o par de uma Service Account comum gera token, mas o servidor MCP responde 403. O teste lista cerca de 40 ferramentas.
  • Cada ferramenta fica Livre, Pedir aprovação ou Bloqueada. No Supabase, list_tables Livre e execute_sql pedindo aprovação; no Atlas, o botão 🛡️ Sugestão segura deixa o que só lê Livre, aggregate e export pedindo aprovação e o resto bloqueado.
🔒 Rede privada (Tailscale)

Banco na empresa, sem abrir porta

O MySQL do sistema da loja, o PostgreSQL do ERP, o SQL Server do escritório. O computador do banco e o servidor da FlexPage entram numa rede privada cifrada e o site conversa com o banco por dentro dela. Nada de abrir a porta 3306 para a internet.

  • O técnico instala o Tailscale na máquina do banco, com a chave de acesso que a equipe FlexPage fornece. A máquina entra na rede privada da FlexPage e só recebe conexões do servidor dela, nas portas de banco.
  • Em ⚙️ Backend → 💾 Armazenamento de Dados, o Host é o endereço do banco na rede privada e o campo 🔒 Rede privada recebe 100.101.102.103:3306, com Salvar liberação. Só administrador altera essa lista.
  • O servidor só alcança as portas de banco (3306, 5432, 1433) das máquinas liberadas, e cada site só alcança o endereço liberado para ele.

Disponível em qualquer plano, com setup único de R$ 799. As três travas, passo a passo.

📄 Sem banco externo

O banco do próprio app

Nem todo projeto precisa de um servidor de banco. Para cadastros pequenos — lista de inscritos, catálogo, controle simples — o backend do site lê e grava arquivos JSON na pasta do próprio site, pela classe FileManager. A documentação recomenda particionar em vários arquivos quando o volume passa de 10.000 registros.

O SQLite já vem incluído e funciona sem configurar nada — é o ponto de partida natural para quem ainda não tem banco. O guia mostra os dois caminhos.

Antes de escolher, pense em quem lê o dado. Relatório para o dono do negócio combina com db_query e com o Harness. Dado de um cliente específico (os agendamentos dele, os pedidos dele) combina com função do app, que roda com o usuário logado — veja a seção sobre o agente mais abaixo.
Compatibilidade

Quais bancos são aceitos

O nome é o que aparece no produto. Se o seu banco é compatível com um deles, escolha a linha correspondente no campo Banco.

OndeBancos
🗄️ Conexão direta
MySQL, MariaDB, PostgreSQL, Supabase
MySQL, MariaDB, PostgreSQL, Supabase ou um compatível — TiDB, Amazon Aurora, Google Cloud SQL, PlanetScale, Neon, CockroachDB e YugabyteDB.
🗃️ Bancos NoSQL
Firestore e DynamoDB
Google Firestore (Firebase) e Amazon DynamoDB. Em 🔌 Conectores → 🗃️ Bancos NoSQL → ➕ Novo banco NoSQL. Ferramentas: nosql_schema, nosql_get, nosql_query e nosql_count (contar e somar sem trazer os documentos).
🔌 Conector MCP
Servidor MCP pronto
Supabase (token) e MongoDB Atlas (Client ID e Secret de uma MCP configuration). Também serve qualquer servidor MCP remoto com https; endereços internos são bloqueados.
🔒 Rede privada
Banco dentro da empresa
MySQL, MariaDB, PostgreSQL, SQL Server e Oracle num servidor da empresa, no escritório ou numa máquina virtual.
Sem instância própria SQLite, que já vem incluído, e os arquivos JSON do próprio site. Nos planos publicados no site, Aurora, MSSQL, Oracle, Snowflake e Teradata aparecem no plano Enterprise.
Credencial de cada NoSQL. No Firestore você cola o JSON da conta de serviço do Google Cloud (IAM → Contas de serviço, com o papel Cloud Datastore Viewer → Chaves → Adicionar chave); o ID do projeto pode ficar vazio, porque vem do JSON. No DynamoDB são o Access Key ID e o Secret Access Key de um usuário IAM com a política AmazonDynamoDBReadOnlyAccess, mais a Região (ex.: sa-east-1). O ⚡ Testar responde em português quando algo está errado — ID de projeto, API do Firestore desativada ou chave da AWS.
Agente de atendimento

O agente consulta sem escrever SQL

O conector serve ao Harness, no painel. O site no ar e os agentes não usam o conector: o app tem a própria conexão com o banco e o agente trabalha pelas funções. É o desenho mais seguro — o agente conversa com qualquer pessoa, então só pode fazer o que as funções permitem.

1 · Cliente logado“Quais são meus horários? Cancela o de amanhã.”
2 · Agente pede funçõesmeus_agendamentos, cancelar_agendamento
3 · O app consultasó os agendamentos do telefone do cliente logado
4 · Confirmaçãoa tela mostra o que vai ser cancelado e o cliente diz “sim”

1. Ligar o site ao banco

  • No Supabase, copie a Project URL (Project Settings → API) e a senha do banco (Project Settings → Database — a que você definiu ao criar o projeto; se não lembrar, use Reset database password). É a senha do Postgres, não a chave anon nem a service_role.
  • No painel, em Gerar Site por IA, abra 💾 Armazenamento de Dados e escolha a opção do banco (ex.: ⚡ Supabase).
  • Preencha Project URL e 🔑 Senha do banco; deixe Usar Service Role? em Não. Clique em 💾 Salvar Configuração.
  • O painel grava a conexão cifrada em db_config.json, dentro do site. O código lê esse arquivo: a senha não aparece no código nem na conversa com o Harness.

2. Declarar as funções do agente

Em 🤖 Agentes, o campo Funções (JSON) recebe o que o agente pode pedir. Quem responde é o código do app — nunca o contrário.

Funções do recepcionista
[
  {
    "nome": "meus_agendamentos",
    "descricao": "Lista os próximos agendamentos confirmados do
      cliente logado, com o id de cada um.",
    "parametros": {}
  },
  {
    "nome": "cancelar_agendamento",
    "descricao": "Cancela um agendamento do cliente logado pelo
      id que veio de meus_agendamentos.",
    "parametros": { "id": "integer" },
    "confirmar": true
  }
]
Regra de ouro. O código do app nunca confia no que o agente manda sobre quem é o cliente: o cliente é sempre o que está logado no app. Se alguém escrever “cancele o horário do cliente 42”, o app continua só alcançando os agendamentos de quem está logado — na prática, WHERE telefone = ? com o telefone vindo do login, nunca do agente.

Função que altera dado pede o “sim”

Marcando "confirmar": true na função, a tela mostra o que vai acontecer e só executa depois da confirmação do cliente:

ClienteNão vou conseguir ir amanhã, cancela pra mim.
Cancelar o agendamento Corte com Rafa · amanhã às 9h?
[ Sim, cancelar ] [ Não ]
recepcionistaPronto, cancelado. Quando quiser remarcar, é só chamar!

E se o agente precisar consultar um sistema externo?

O agente do app também pode consultar um conector, só para leitura, com três travas:

  • 1 · O admin libera: no conector, marque Liberar para agentes de app (🤖) — só leitura.
  • 2 · O agente pede: no cadastro do agente, marque o conector na caixa Conectores (só leitura).
  • 3 · Só o que é Livre: entram apenas as ferramentas marcadas Livre, uma a uma — o modo “Padrão” não conta.

A credencial é do administrador, não do cliente: dado que é de um cliente continua sendo função do app. Conector no agente é para informação que qualquer cliente pode ver — catálogo, disponibilidade, horário de funcionamento.

Segurança

O que trava o quê, item por item

Nada disso depende de você lembrar de uma regra: são travas do próprio produto e do próprio banco.

Credencial cifrada

A senha da conexão fica cifrada e só aparecem os 4 últimos caracteres. Tokens de conector nunca voltam para a tela, e a conexão que o app usa fica em db_config.json — não no código.

Usuário só-leitura

Crie no banco um usuário que só tenha permissão de SELECT e cadastre esse no Harness: mesmo que algo dê errado, o banco recusa a alteração. O ideal é o app ter um usuário próprio com gravação, e o Harness continuar com o de leitura.

“Permitir que a IA leia registros” desligada

O recomendado. O Harness vê a estrutura e resultados agregados — contagens, somas, médias, datas. “Quantos agendamentos por barbeiro?” funciona; “liste os clientes de amanhã” ele explica por que não pode.

Colunas que nunca saem

Senha, token, secret e api_key nunca vão para a IA. Com a leitura de registros desligada, também não saem telefone, celular, WhatsApp, CPF, CNPJ, RG, latitude/longitude e nascimento — pelo nome da coluna. Em Colunas sempre bloqueadas o administrador acrescenta as suas (ex.: observacao).

Prazo da consulta

Cada consulta tem um Prazo da consulta — padrão 30 s, até 110 s — cortado no Harness e no próprio banco. Se estourar, ele avisa e sugere filtrar por uma coluna com índice.

Parâmetro no lugar de texto colado

O SQL do app usa ? com os valores num array. Isso evita que um texto digitado vire comando dentro do banco.

TentativaO que acontece
Alterar dados (INSERT, UPDATE, DELETE) sem liberaçãoNão existe: a conexão só executa se o administrador ligar Permitir alterações com aprovação. Com o read_only=true do Supabase, o próprio banco recusa.
Comando sem WHERE na alteraçãoRecusado, a menos que você tenha pedido isso de propósito — e o cartão avisa.
CREATE, ALTER, DROPNunca executa: mostra o SQL para você rodar onde quiser.
Alguém mexe no registro entre a prévia e o seu “Permitir”O número de linhas não bate e nada é gravado; ele consulta de novo.
Sessão em “Executar direto” e o pedido altera o bancoO cartão de aprovação aparece mesmo assim: alterar o banco sempre pede aprovação.
Um site tentar outro endereço da rede privada, ou 127.0.0.1Recusado: só vale o host:porta liberado para aquele site, conferido a cada conexão.
Endereço de metadados da nuvem (169.254.169.254)Nunca é liberado, nem pelo administrador.
O ↶ Desfazer do painel não volta o banco. Ele desfaz arquivos, não dados. Por isso existe a prévia: o comando roda numa transação e é desfeito, só para contar as linhas — o cartão mostra “vai alterar 1 linha(s)” e você aprova vendo o SQL. Se o número parecer grande demais para o que você pediu, recuse.
Como é na prática

Uma pergunta, três respostas possíveis

Estes são exemplos do próprio guia do Harness, com uma base de barbearia: serviços, barbeiros e agendamentos.

1 · estruturaMostre a estrutura do banco da agenda: tabelas, colunas e como se ligam.
🗄️ db_schema · agenda · visão geral
HarnessSão 3 tabelas: servicos (nome, preço, duração), barbeiros (nome, atende_sabado) e agendamentos, que liga as duas pelo servico_id e barbeiro_id.
2 · relatórioQuanto cada barbeiro vai faturar com os agendamentos confirmados desta semana?
🧮 db_query · agenda · SELECT b.nome, SUM(s.preco) … GROUP BY b.nome
HarnessRafa: R$ 105 (2 agendamentos). Léo: R$ 100 (3 agendamentos).
3 · proteçãoListe nome e telefone dos clientes de amanhã.
HarnessA leitura de registros está desligada nesta conexão: só vejo números e datas. Posso dizer que amanhã há 3 agendamentos (09h, 10h e 14h). Para ver nomes, o administrador liga “Permitir que a IA leia registros”.
Por que a terceira resposta é boa notícia. O relatório de faturamento sai na hora, com número real; e o nome e o telefone dos clientes não saem para o provedor de IA. Quem precisa desse dado é o app, no atendimento — e ali a trava é outra: a função roda com o usuário logado.
Para quem desenvolve

O miolo do código que o Harness escreve

O app usa a classe DatabaseClient do runtime e lê a configuração cifrada do painel. O Harness escreve esse código para você — e você confere os cinco pontos da tabela antes de aprovar.

script/api.js (trecho)
function comBanco(fn) {
    var db = new DatabaseClient();
    db.connect(loadDbConfig());        // db_config.json cifrado pelo painel
    try { return fn(db); } finally { db.close(); }
}

var handlers = {
    meus_agendamentos: function () {
        return comBanco(function (db) {
            return { agendamentos: db.query(
                "SELECT a.id, s.nome AS servico, b.nome AS barbeiro, a.inicio " +
                "FROM agendamentos a " +
                "JOIN servicos s ON s.id = a.servico_id " +
                "JOIN barbeiros b ON b.id = a.barbeiro_id " +
                "WHERE a.telefone = ? AND a.status = 'confirmado' " +
                "AND a.inicio > now() ORDER BY a.inicio",
                [cliente.telefone]) };   // do login, nunca do agente
        });
    }
};

// cancelar_agendamento só roda depois do "sim" do cliente:
function cancelar(db, id) {
    return db.execute("UPDATE agendamentos SET status = 'cancelado' " +
        "WHERE id = ? AND telefone = ? AND status = 'confirmado'",
        [id, cliente.telefone]);
}
Procure no código propostoPor quê
require('DatabaseClient') e a leitura de db_config.jsonUsa a conexão cifrada do painel, sem chave no código.
? nos SQL, com os valores num arrayEvita que um texto digitado vire comando no banco.
WHERE … telefone = ? com o telefone do cliente logadoCada cliente só vê e cancela os próprios horários.
cancelar_agendamento sem handler direto, passando pela confirmaçãoO cancelamento só acontece depois do “sim”.
db.close() num finallyNão deixa conexões abertas.
O botão 📄 ao lado da conexão, no painel, gera o db_config.json de um site a partir dela. Um pedido que funciona bem, numa sessão do tipo 📱 App: “Leia as tabelas do banco pelo conector e implemente no script/api.js as funções do agente, usando o DatabaseClient com a configuração do db_config.json. O cliente é sempre o telefone do usuário logado, nunca um dado vindo do agente.”
Dúvidas frequentes

Perguntas de quem vai ligar o banco

Quais bancos a FlexPage aceita?

Na conexão direta do painel: MySQL, MariaDB, PostgreSQL, Supabase e compatíveis (TiDB, Amazon Aurora, Google Cloud SQL, PlanetScale, Neon, CockroachDB e YugabyteDB). Em bancos NoSQL: Google Firestore e Amazon DynamoDB. Por conector MCP: Supabase e MongoDB Atlas. Pela rede privada, com o banco dentro da empresa: MySQL, MariaDB, PostgreSQL, SQL Server e Oracle.

O agente de atendimento escreve SQL?

Não. O site no ar e os agentes não usam o conector do painel: o app tem a própria conexão com o banco e o agente só chama as funções que o app declara, como meus_agendamentos e cancelar_agendamento. Cada função roda com o usuário logado, então um cliente nunca alcança o dado de outro — e função que altera dado pede a confirmação do cliente.

Os dados dos meus clientes vão para a IA?

Por padrão, não. Com a leitura de registros desligada, o Harness vê a estrutura e resultados agregados: contagens, somas, médias e datas. Senha, token, secret e api_key nunca saem; com a leitura desligada também não saem telefone, celular, WhatsApp, CPF, CNPJ, RG, latitude/longitude e nascimento. Em Colunas sempre bloqueadas o administrador acrescenta as colunas dele.

Meu banco fica num computador da empresa. O site consegue usar?

Sim, sem abrir o banco para a internet. O computador do banco e o servidor da FlexPage entram numa rede privada cifrada (Tailscale) e o administrador libera no painel, por site, o endereço e a porta daquele banco. O endereço é conferido a cada conexão e nenhum outro site alcança o seu banco. Veja as três travas.

Ficou alguma dúvida? Pergunte no WhatsApp →

Seu banco, no site

Conte qual banco você tem — a gente diz o melhor caminho

Diga se ele está na nuvem ou num computador da empresa, e o que você quer mostrar na tela. A resposta vem com o caminho certo: conexão direta, conector, rede privada ou arquivo no próprio site.

Continue lendo: agentes por API · automações e rotinas · home da FlexPage

Fale conosco