listSources
nunca ejecutaDescubrimiento. Fuentes conectadas con campos tipados, módulos de capacidad, firmas de función — tres modos desde una sola entrada, para que las specs usen nombres exactos.
Para agentes — la herramienta de datos gobernada
SQAI da a un modelo con llamada a herramientas acceso de solo lectura a datos estructurados a través de tres herramientas gobernadas. El modelo redacta intención tipada. Un contrato y tu política la verifican. Un motor determinista la ejecuta. Cada respuesta incluye un hash que la reproduce.
IUn turno del bucle
“¿Qué región tuvo los mayores ingresos totales?”Planifica los pasos. Redacta la intención. Nunca toca los datos.
{ version:"1", kind:"query", spec:{ metric:"revenue", aggregation:"sum", group_by:"region", source:"sales" } }contractcontrato de capacidad fijado por hashpolicytus listas de permisos, verificadas antes de la ejecuciónengineejecución determinista y de solo lecturastatus: ok · needs_clarification · rejected · erroreast — 2,130.50 · plan_hash f87610d8afeb…okSale del bucle. Las filas o el valor — y el hash que los reproduce.
needs_clarification ↺Vuelve al bucle. Una pregunta y los candidatos encontrados — el modelo refina la especificación y llama de nuevo. Nunca adivina una columna.
los rechazos y los errores usan el mismo canal de retorno — resultados tipados que el modelo puede leer, no excepciones que abortan la ejecución.
IILas herramientas
sqai.tools() devuelve exactamente tres herramientas — una superficie deliberadamente pequeña. El descubrimiento y los ensayos nunca ejecutan; la ejecución ocurre en un único lugar.
listSourcesDescubrimiento. Fuentes conectadas con campos tipados, módulos de capacidad, firmas de función — tres modos desde una sola entrada, para que las specs usen nombres exactos.
queryDataUna entrada versionada — una unión discriminada sobre kind: una consulta o un cómputo. Cuatro resultados, siempre tipados, sin excepciones.
explainQueryResuelve y valida una intención sin ejecutarla. El modelo la usa para depurar aclaraciones; tú la usas para previsualizar un plan.
El conjunto se integra directamente en generateText o streamText — tipado, asignable sin cast. Configuración de Vercel AI SDK →
IIIEl contrato de errores
Una excepción aborta una ejecución del agente. Por eso nada aquí lanza: la ambigüedad, el rechazo y el fallo regresan como estados tipados que el modelo puede leer — y corregir — dentro de su presupuesto de pasos.
retryable marca los transitorios — network_error · timeout · rate_limited · service_unavailable
queryData — los cuatro resultados
okEl resultado: filas o valor, hashes de procedencia, truncación declarada.plan_hash · invocation_hash · computation_hash · truncatedneeds_clarificationLa intención era ambigua. Una pregunta más los candidatos — nunca una suposición.question · candidates · explanationrejectedEl resolver rechazó la intención. Nada se ejecutó.rejection_reason · candidates · explanationerrorUn fallo estructurado con un código estable — el modelo lo lee y se ajusta.code · message · retryable · nearest_matches?Cada rama es dato. El bucle conserva su turno.
El principio
política en código · ningún campo de política en ninguna entrada de tool · solo restricción
IVEl principio, aplicado
La industria aprendió esto en producción — un agente de codificación autónomo eliminó célebremente una base de datos en vivo. La respuesta de SQAI es estructural, no conductual: la superficie expuesta es de solo lectura por construcción. Las categorías de escritura y no deterministas nunca se generan en ella, y ningún flag, política ni entrada del modelo las reactiva.
VLa conexión
Un paquete envuelve el cliente en tools. Las fuentes se conectan de forma diferida en la primera llamada; el primer cómputo aprovisiona el runtime una vez y luego permanece activo — 0,83 ms medidos.
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?",
});Solo en servidor — en Next.js, usa el runtime de Node, no Edge.
Lo que llega al modelo
El truncamiento siempre se declara — truncated: true, returned_rows < total_rows. Nunca silencioso. Los resultados completos siguen siendo recuperables en el código de aplicación mediante result_id.
VIAnalítica agéntica
La analítica agéntica falla de formas conocidas: llamadas a tools malformadas, modelos haciendo su propia aritmética, números plausibles que nadie puede verificar. Cada problema se resuelve de forma estructural, no con un mejor prompt.
Una entrada versionada, validada antes de que nada se ejecute. Una intención malformada o ambigua devuelve un estado tipado — el bucle continúa en lugar de fallar.
Aquí no. El motor computa. En un conjunto cuantitativo de 16 preguntas, el mismo modelo pasó de 0/16 a 16/16 en cuanto el motor asumió el cómputo.
Cada respuesta lleva su hash. Reproduce la misma intención sobre los mismos datos y el hash coincide — idéntico byte a byte en TypeScript y Python.
Un bucle multiplica la latencia. El plano de consulta se ejecuta en proceso a submilisegundo; el cómputo en caliente se midió en 0,83 ms.
VIIPreguntas
No filtres SQL — no lo generes. Conecta fuentes a createSQAI() y entrega al modelo sqai.tools(): la superficie a la que accede son 4.574 capacidades de solo lectura más tus fuentes, sin ruta de escritura por construcción. No existe ninguna categoría de escritura que bloquear, ni ninguna entrada del modelo que la reactive.
queryData devuelve needs_clarification con una pregunta y los campos candidatos encontrados. Nunca infiere una columna. El modelo responde la pregunta y vuelve a llamar: una vuelta más del bucle.
No. Cada fallo es un resultado estructurado con un código estable, un mensaje y un indicador de reintento. Ambigüedad, rechazo, denegación de política y fallos transitorios vuelven todos como datos que el modelo puede leer.
No. allowedSources, allowedFields y allowedFunctions viven en el código, fijados en el momento de createSQAI() y verificados antes de la ejecución. Ningún esquema de entrada de herramienta contiene un campo de política; nombrar una capacidad denegada devuelve un error estructurado policy_denied.
Sí — @thyn-ai/sqai-ai-sdk incluye las tres herramientas como conjunto tipado para generateText y streamText, con ai ^7.0.0 y zod ^4.0.0 como peers, Node 20 o superior, en servidor. El cliente subyacente es el mismo SDK que puede integrarse en cualquier bucle de agente.