Per gli agenti — lo strumento dati governato

Strumenti per agenti AI
che rispondono con prove.

SQAI offre a un modello con tool-calling accesso in sola lettura ai dati strutturati tramite tre strumenti governati. Il modello esprime intento tipizzato. Un contratto e la tua policy lo verificano. Un motore deterministico lo esegue. Ogni risposta torna con un hash che la riproduce.

IUn turno del ciclo

la richiesta entraQuale regione ha avuto il fatturato totale più alto?
qualsiasi modello con tool-callingIl modello

Pianifica i passi. Esprime l'intento. Non tocca mai i dati.

tool call — intento tipizzato, mai SQL{ version:"1", kind:"query", spec:{ metric:"revenue", aggregation:"sum", group_by:"region", source:"sales" } }
lo strumento governatoSQAI
  1. contractcontratto di capability fissato con hash
  2. policyle tue allow-list, verificate prima dell'esecuzione
  3. engineesecuzione deterministica, in sola lettura
stato tipizzato — mai un'eccezionestatus: ok · needs_clarification · rejected · error
la risposta esce — con il suo hasheast — 2,130.50 · plan_hash f87610d8afeb…
ok

Esce dal ciclo. Le righe o il valore — e l'hash che li riproduce.

needs_clarification ↺

Rientra nel ciclo. Una domanda e i candidati trovati — il modello affina la spec e chiama di nuovo. Non indovina mai una colonna.

rifiuto ed errore percorrono lo stesso canale di ritorno — risultati tipizzati che il modello può leggere, non eccezioni che interrompono l'esecuzione.

IIGli strumenti

Tre strumenti. Uno esegue.

sqai.tools() restituisce esattamente tre strumenti — una superficie deliberatamente ridotta. Discovery e dry run non eseguono mai; l'esecuzione avviene in un solo punto.

listSources

non esegue mai

Discovery. Sorgenti connesse con campi tipizzati, moduli di capability, firme di funzione — tre modalità da un unico input, così le spec usano nomi esatti.

sources · capabilitySearch · module
ops: sum avg count min max eq in gt gte lt lte is_null is_not_null

queryData

quello che esegue

Un unico input versionato — una discriminated union su kind: una query o un calcolo. Quattro esiti, sempre tipizzati, mai un'eccezione.

version "1" · kind: query | computation
ok · needs_clarification · rejected · error

explainQuery

dry run — non esegue mai

Risolve e valida un'intenzione senza eseguirla. Il modello la usa per diagnosticare i chiarimenti; tu la usi per visualizzare un piano.

preview invocation_hash ≠ executed hash

Il set si inserisce direttamente in generateText o streamText — tipizzato, assegnabile senza cast. Configurazione Vercel AI SDK

IIIIl contratto d'errore

I tool non lanciano eccezioni.

Un'eccezione interrompe un'esecuzione agente. Quindi nulla qui lancia: ambiguità, rifiuto e fallimento tornano come stati tipizzati che il modello può leggere — e correggere — nel suo budget di step.

retryable contrassegna quelli transitori — network_error · timeout · rate_limited · service_unavailable

queryData — i quattro esiti

okIl risultato: righe o valore, hash di provenienza, troncamento dichiarato.plan_hash · invocation_hash · computation_hash · truncated
needs_clarificationL'intenzione era ambigua. Una domanda con i candidati — mai un'ipotesi.question · candidates · explanation
rejectedIl resolver ha rifiutato l'intenzione. Nulla è stato eseguito.rejection_reason · candidates · explanation
errorUn fallimento strutturato con un codice stabile — il modello lo legge e si adegua.code · message · retryable · nearest_matches?

Ogni ramo è dato. Il loop mantiene il suo turno.

Il principio

Tratta il modello come
un client non attendibile.

policy nel codice · nessun campo policy in alcun input tool · solo restrizione

IVIl principio, applicato

Il settore lo ha imparato in produzione — un agente di coding autonomo ha cancellato notoriamente un database live. La risposta di SQAI è strutturale, non comportamentale: la superficie esposta è in sola lettura per costruzione. Le categorie di scrittura e non deterministiche non vi vengono mai generate, e nessun flag, policy o input del modello le riattiva.

Cosa invia il modello
Solo intenzione tipizzata — una spec versionata. Nessuna stringa SQL, nessun codice, nessun handle di connessione.
Cosa non può mai inviare
La policy. allowedSources, allowedFields e allowedFunctions sono fissati nella configurazione di createSQAI() — nessuno schema di input tool contiene un campo policy, quindi una richiesta può restringere la superficie ma non allargarla mai.
Quando lo chiede comunque
Un rifiuto strutturato — policy_denied_source, policy_denied_field, policy_denied_function. Non ritentabile, leggibile dal modello, e l'esecuzione continua.
Modello di policy completo

VIl collegamento

Tre righe. Limitato per default.

Un pacchetto avvolge il client in tool. Le sorgenti si connettono in modo lazy alla prima chiamata; il primo calcolo provisiona il runtime una volta, poi rimane attivo — 0,83 ms misurati.

import { generateText } from "ai";
import { createSQAI } from "@thyn-ai/sqai-ai-sdk";

const sqai = createSQAI({
  sources: [{ data: "./data/sales.csv", name: "sales" }],
});

const { text, steps } = await generateText({
  model,                  // any AI SDK model
  tools: sqai.tools(),    // listSources · queryData · explainQuery
  prompt: "Which region had the highest total revenue?",
});
ai ^7.0.0zod ^4.0.0node ≥ 20runtime = "nodejs"

Solo lato server — su Next.js, mantieni il runtime Node, non Edge.

Cosa raggiunge il modello

maxRowsToModel
25righe visibili al modello, sul totale eseguito dal motore
maxCellsToModel
250budget di celle — le righe intere vengono scartate per rientrare; una riga parziale non viene mai mostrata
maxBytesToModel
32,000budget in byte per il valore visibile al modello
maxExecutionRows
1,000limite massimo eseguito dal motore — defaultLimit 100 quando una spec omette il limite

Il troncamento è sempre dichiarato — truncated: true, returned_rows < total_rows. Mai silenzioso. I risultati completi rimangono recuperabili nel codice applicativo tramite result_id.

VIAnalytics agentici

Analisi che un agente sa difendere.

Gli analytics agentici falliscono in modi noti: chiamate tool malformate, modelli che fanno i propri calcoli, numeri plausibili che nessuno può verificare. Ognuno trova risposta strutturale, non in un prompt migliore.

01Chiamate tool non valide

Un unico input versionato, validato prima di qualsiasi esecuzione. Un'intenzione malformata o ambigua restituisce uno stato tipizzato — il loop continua invece di crashare.

02Il modello fa i calcoli

Non qui. Calcola il motore. Su un set quantitativo di 16 domande, lo stesso modello è passato da 0/16 a 16/16 non appena il calcolo è stato affidato al motore.

03Numeri non verificabili

Ogni risposta porta il suo hash. Ripeti la stessa intenzione sugli stessi dati e l'hash corrisponde — identico al byte in TypeScript e Python.

04Accumulo di latenza

Un loop moltiplica la latenza. Il piano di query gira in-process a sub-millisecondo; il calcolo a caldo misurato a 0,83 ms.

VIIDomande

Per gli agenti — le domande

Come si dà a un agente AI accesso in sola lettura a un database?

Non filtrare SQL — non generarlo. Connetti le sorgenti a createSQAI() e passa al modello sqai.tools(): la superficie che raggiunge è 4.574 capability in sola lettura più le tue sorgenti, senza percorso di scrittura per costruzione. Non esiste una categoria di scrittura da bloccare, né alcun input del modello che la riabiliti.

Cosa succede quando la richiesta dell'agente è ambigua?

queryData restituisce needs_clarification con una domanda e i campi candidati individuati. Non ipotizza mai una colonna. Il modello risponde alla domanda e chiama di nuovo — un altro giro del ciclo.

Gli strumenti generano mai un'eccezione?

No. Ogni errore è un risultato strutturato con un codice stabile, un messaggio e un flag retryable. Ambiguità, rifiuto, diniego di policy e guasti transitori tornano tutti come dati leggibili dal modello.

Il modello può ampliare i propri permessi?

No. allowedSources, allowedFields e allowedFunctions vivono nel codice, impostati al momento di createSQAI() e verificati prima dell'esecuzione. Nessuno schema di input degli strumenti contiene un campo di policy; nominare una capability negata restituisce un errore strutturato policy_denied.

Funziona con il Vercel AI SDK?

Sì — @thyn-ai/sqai-ai-sdk distribuisce i tre strumenti come typed tool set per generateText e streamText, con ai ^7.0.0 e zod ^4.0.0 come peer, Node 20 o superiore, lato server. Il client sottostante è lo stesso SDK collegabile a qualsiasi ciclo agente.