Planilhas com SQL
Consulte as células de todas as planilhas com uma instrução SQL e preencha relatórios sem que os dados passem pelo agente.
Cada planilha .xlsx, .xlsm ou .csv enviada vira fatos que o agente consulta com SQL. Uma pergunta sobre dez planilhas cabe em uma chamada sql, em vez de dez leituras de arquivo. sql, sql_schema, sql_write e sheet_write são ferramentas MCP.
Quando os fatos ficam prontos
Todo arquivo tem um status, que get, list, file_read e document_search informam; os que não estão ready trazem em statusMessage o que fazer:
| Status | Significado |
|---|---|
processing |
O arquivo ainda está sendo lido. |
ready |
As células ou o texto já podem ser consultados. |
too_large |
O arquivo passa do limite de células ou de tamanho por planilha. Ele continua disponível para download; divida-o em partes menores e envie de novo. |
limit_reached |
Os dados processados da organização chegaram ao limite da organização. O arquivo fica guardado e é lido sozinho quando houver espaço: quando a equipe da Siglata aumenta o limite, ou ao apagar arquivos ou tabelas SQL. |
failed |
O arquivo não pôde ser lido. |
stored |
Um tipo que a Siglata guarda, mas não lê, como um vídeo. |
Enquanto a versão atual de uma planilha está em processing, sql lê a última versão pronta e diz em warnings qual versão leu; uma planilha sem versão pronta aparece em warnings em vez de sumir do resultado.
A Siglata guarda apenas fatos determinísticos: nunca recalcula fórmulas, nunca adivinha versões nem localidades. A interpretação fica com o agente.
Tabelas e funções
Chame sql_schema para ver as colunas de cada tabela, as funções e os objetos que você pode ler.
| Tabela | Conteúdo |
|---|---|
sheet_files |
Um registro por planilha, com o estado dos fatos. |
cells |
Uma linha por célula: arquivo, aba, endereço, linha, coluna, texto bruto, valor tipado, fórmula e formato numérico. |
styles |
Fonte, preenchimento, borda e alinhamento de cada estilo. |
sheets |
Abas e intervalos usados. |
excel_tables |
Tabelas do Excel. |
defined_names |
Nomes definidos. |
merges |
Células mescladas. |
| Função | Uso |
|---|---|
sheet_rows(file, sheet) |
Linhas largas de uma aba, com as colunas por letra (A, B, C…). |
table_rows(target uuid) |
Revisão atual de cada registro legível da tabela target, com colunas de auditoria tipadas e o conteúdo em data jsonb. |
parse_number(text, locale) |
Converte texto como 1.234,56 (pt-BR) ou 1,234.56 (en-US) em número. |
parse_date(text, format) |
Converte texto em data com um padrão como DD/MM/YYYY. |
column_letters(col) |
Converte o número da coluna em letras. |
Valores de CSV ficam como texto; use parse_number e parse_date para interpretá-los.
Uma tabela da empresa também se lê como tables.<key>, com a chave que table_list e table_get mostram. Cada registro atual é uma linha: primeiro record_id, revision, created_by, changed_by, created_at, source_file_id, transcript_file_id e unconfirmed_fields text[], depois uma coluna por propriedade de primeiro nível do esquema ativo, na ordem do esquema:
| Propriedade | Coluna |
|---|---|
string |
text |
string com format: date |
date |
string com format: uuid, ou uma referência |
uuid |
integer |
bigint |
number |
numeric |
boolean |
boolean |
| lista de opções em texto | text[] |
| qualquer outra | jsonb |
SELECT v.visited_on, l.name AS loja, v.amount
FROM tables.visitas v
JOIN tables.lojas l ON l.record_id = v.store
WHERE 'loja' = ANY(v.types)
As colunas seguem o esquema ativo a cada chamada; colunas text[] voltam como listas JSON de textos. Uma propriedade com nome vazio, com mais de 63 bytes ou igual a uma coluna fixa não vira coluna, e tables.<key> é recusada nomeando-a; leia essa tabela com table_rows. Para que toda coluna tipada caiba no seu tipo, um registro com um inteiro além de ±9007199254740991, uma data no ano 0000 ou um UUID fora da forma canônica (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) é recusado. Se um registro salvo antes dessa regra tiver um desses valores, tables.<key> é recusada nomeando a propriedade até que o registro seja corrigido. Se o esquema ativo da tabela mudar enquanto a consulta é preparada, sql falha com conflict; basta repetir a chamada. sql_write recusa views e snapshots que leem tables.<key>: consulte tables.<key> direto ou crie a view sobre table_rows.
tables.<key> e table_rows retornam seus próprios registros, ou todos quando você criou a tabela, suas permissões atuais permitem ler todos os registros ou a tabela mostra os registros a toda a empresa. Projete campos escalares com data->>'campo', #>> ou as funções de extração de JSON; revision e schema_revision são inteiros. source_file_id fica nulo quando o arquivo de origem não está no seu escopo de leitura. Views consultam novamente as permissões de cada chamada. Snapshots SQL de tabelas, inclusive por meio de views, não são aceitos; use uma view ou uma exportação de tabela com verificação de permissões.
Consultar
sql (files:read) executa um único SELECT na sintaxe do Postgres:
return await sql({
query: `SELECT raw AS filial, count(*) AS celulas
FROM cells
WHERE sheet = 'Vendas' AND col = 2 AND row >= 2
GROUP BY raw`,
});
- Devolve as linhas que cabem em 23.000 bytes de JSON, sem limite de linhas, e roda por no máximo 10 s. Quando algo fica de fora, a resposta traz
truncated: trueenext, que explica como paginar comORDER BYeLIMIT/OFFSETou estreitar oSELECT. - Nomeie tabelas sem esquema; só uma tabela da empresa leva um, como
tables.<key>. Só as funções e os tipos listados são aceitos; catálogos do sistema e comandos que alteram dados são recusados. - Antes de um comando rodar, a Siglata limita a memória do banco que ele poderia usar no pior caso, pelos valores mais longos das tabelas que ele lê e por uma regra de tamanho para cada função, operador e conversão, através de cada CTE, subconsulta e view. Um comando acima de 128 MiB é recusado com
too_large, antes de rodar, emSELECT,CREATE VIEWeCREATE TABLE AS: monte valores menores (menosconcat,replace, conversões ou construtores de JSON e de array aninhados), selecione menos colunas ou divida o trabalho.WITH RECURSIVEé recusado (usegenerate_series), e um padrão de expressão regular ou deSIMILAR TOprecisa ser uma constante de texto de no máximo 2.000 estados compilados. No máximo 4 comandos rodam ao mesmo tempo; um comando que encontra todos ocupados falha comconflict, e basta tentar de novo. - Cada recusa tem um código, como
relation_not_allowed,function_not_allowed,timeoutouconflict(repita a chamada).
Views e snapshots
sql_write (files:write) cria e remove objetos seus:
| Instrução | Resultado |
|---|---|
CREATE VIEW nome AS SELECT … |
Uma view compartilhada com a organização. Cada membro a lê com o próprio acesso. |
CREATE TABLE nome AS SELECT … |
Um snapshot que só você lê, sobre sources (os ids dos arquivos que ele pode ler; se omitido, todos os que você lê quando a consulta lê as tabelas de fatos, sheet_rows ou uma view, e só as fontes dos snapshots que ela lê nos outros casos). Conta no limite de planilhas que o agente consulta. |
DROP VIEW nome ou DROP TABLE nome |
Remove um objeto que você criou. |
return await sql_write({
query:
"CREATE TABLE vendas_agosto AS SELECT raw FROM cells WHERE sheet = 'Agosto'",
sources: ["<id da planilha>"],
});
Um snapshot segue os arquivos de origem: fica oculto enquanto uma origem está na lixeira, volta quando ela é restaurada e é removido quando ela é excluída definitivamente.
Preencher um relatório
sheet_write aceita um patch de consulta { sheet, anchor, query } (exige também files:read). Ele roda o SELECT e escreve todas as linhas a partir da célula anchor de uma nova versão do modelo, mantendo a formatação:
return await sheet_write({
fileId: "<id do modelo>",
baseVersion: 1,
requestId: "vendas-setembro-2026",
patches: [
{
sheet: "Relatório",
anchor: "A2",
query: "SELECT filial, receita FROM vendas_mes",
},
],
});
As linhas não passam pelo contexto do agente; a resposta traz apenas o arquivo na nova versão e o intervalo escrito. Um resultado acima de 5.000 linhas, 8 MiB ou 1.000.000 de células falha com too_large, sem acrescentar uma versão.
Permissões
O SQL vê apenas as células dos arquivos ativos que o usuário da conexão pode ler. Um arquivo restrito exige uma permissão; outra organização nunca aparece. Arquivos na lixeira ficam ocultos até serem restaurados.